diff --git a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index e4b0843..a6e38d3 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -11,11 +11,11 @@ using Xunit; namespace CoreIntegrationTests.Infrastructure { - public abstract class MongoDbTKeyDocumentTestBase : + public abstract class MongoDbTKeyDocumentTestBase : IClassFixture> - where T: TestDoc, new() + where T : TestDoc, new() where TKey : IEquatable - + { private readonly MongoDbTestFixture _fixture; @@ -76,7 +76,7 @@ namespace CoreIntegrationTests.Infrastructure // Act SUT.AddOne(document); // Assert - long count = string.IsNullOrEmpty(PartitionKey) ? SUT.Count(e => e.Id.Equals(document.Id)) + long count = string.IsNullOrEmpty(PartitionKey) ? SUT.Count(e => e.Id.Equals(document.Id)) : SUT.Count(e => e.Id.Equals(document.Id), PartitionKey); Assert.True(1 == count, GetTestName()); } @@ -91,7 +91,7 @@ namespace CoreIntegrationTests.Infrastructure // Assert long count = string.IsNullOrEmpty(PartitionKey) ? SUT.Count(e => e.Id.Equals(document.Id)) : SUT.Count(e => e.Id.Equals(document.Id), PartitionKey); - Assert.True (1 == count, GetTestName()); + Assert.True(1 == count, GetTestName()); } [Fact] @@ -106,7 +106,7 @@ namespace CoreIntegrationTests.Infrastructure || e.Id.Equals(documents[1].Id)) : SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); - Assert.True (2 == count, GetTestName()); + Assert.True(2 == count, GetTestName()); } [Fact] @@ -147,7 +147,7 @@ namespace CoreIntegrationTests.Infrastructure || e.Id.Equals(documents[1].Id)) : SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); - Assert.True (2 == count, GetTestName()); + Assert.True(2 == count, GetTestName()); } [Fact] @@ -238,7 +238,7 @@ namespace CoreIntegrationTests.Infrastructure var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); var count = cursor.CountDocuments(); // Assert - Assert.True (1 == count, GetTestName()); + Assert.True(1 == count, GetTestName()); } [Fact] @@ -493,10 +493,10 @@ namespace CoreIntegrationTests.Infrastructure Assert.True(result); var updatedDocument = SUT.GetById(document.Id, PartitionKey); Assert.True(null != updatedDocument); - Assert.True(childrenToAdd[0].Type== updatedDocument.Children[0].Type, GetTestName()); - Assert.True(childrenToAdd[0].Value== updatedDocument.Children[0].Value, GetTestName()); - Assert.True(childrenToAdd[1].Type== updatedDocument.Children[1].Type, GetTestName()); - Assert.True(childrenToAdd[1].Value== updatedDocument.Children[1].Value, GetTestName()); + Assert.True(childrenToAdd[0].Type == updatedDocument.Children[0].Type, GetTestName()); + Assert.True(childrenToAdd[0].Value == updatedDocument.Children[0].Value, GetTestName()); + Assert.True(childrenToAdd[1].Type == updatedDocument.Children[1].Type, GetTestName()); + Assert.True(childrenToAdd[1].Value == updatedDocument.Children[1].Value, GetTestName()); } #endregion Update @@ -512,7 +512,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = SUT.DeleteOne(document); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -525,7 +525,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = SUT.DeleteOne(e => e.Id.Equals(document.Id), PartitionKey); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -538,7 +538,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = await SUT.DeleteOneAsync(document); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -551,7 +551,7 @@ namespace CoreIntegrationTests.Infrastructure // Act var result = await SUT.DeleteOneAsync(e => e.Id.Equals(document.Id), PartitionKey); // Assert - Assert.True (1 == result); + Assert.True(1 == result); Assert.False(SUT.Any(e => e.Id.Equals(document.Id), PartitionKey), GetTestName()); } @@ -768,7 +768,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -790,7 +791,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -812,7 +814,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -834,7 +837,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -856,7 +860,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -878,7 +883,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -900,7 +906,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -908,7 +915,7 @@ namespace CoreIntegrationTests.Infrastructure var expectedMin = documents.OrderBy(e => e.Nested.SomeDate).First(); // Act - var result = SUT.GetMinValue< T, TKey, DateTime >(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + var result = SUT.GetMinValue(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); // Assert Assert.True(result != default(DateTime)); @@ -922,7 +929,8 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; var documents = CreateTestDocuments(5); var i = 1; - documents.ForEach(e => { + documents.ForEach(e => + { e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); e.SomeContent = criteria; }); @@ -930,7 +938,7 @@ namespace CoreIntegrationTests.Infrastructure var expectedMin = documents.OrderBy(e => e.Nested.SomeDate).First(); // Act - var result = await SUT.GetMinValueAsync< T, TKey, DateTime >(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + var result = await SUT.GetMinValueAsync(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); // Assert Assert.True(result != default(DateTime)); @@ -1056,6 +1064,7 @@ namespace CoreIntegrationTests.Infrastructure // Act Expression> ex = x => x.SomeContent4; Expression> ex2 = x => x.SomeContent5; + var result = await SUT.CreateCombinedTextIndexAsync(new[] { ex, ex2 }, null, PartitionKey); // Assert @@ -1119,6 +1128,7 @@ namespace CoreIntegrationTests.Infrastructure #endregion Math #region Test Utils + [MethodImpl(MethodImplOptions.NoInlining)] private string GetCurrentMethod() { diff --git a/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs index 64d9e99..adfe39e 100644 --- a/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IBaseMongoRepository.cs @@ -8,605 +8,16 @@ using System.Linq; namespace MongoDbGenericRepository { - /// /// The IBaseMongoRepository exposes the CRUD functionality of the BaseMongoRepository. /// - public interface IBaseMongoRepository : IReadOnlyMongoRepository, IMongoDbCollectionIndexRepository + public interface IBaseMongoRepository : + IReadOnlyMongoRepository, + IBaseMongoRepository_Create, + IBaseMongoRepository_Update, + IBaseMongoRepository_Delete, + IBaseMongoRepository_Index { - #region Create - - /// - /// Asynchronously adds a document to the collection. - /// - /// The type representing a Document. - /// The document you want to add. - Task AddOneAsync(TDocument document) where TDocument : IDocument; - - /// - /// 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. - void AddOne(TDocument document) where TDocument : IDocument; - - /// - /// Asynchronously adds a list of documents to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The document you want to add. - Task AddManyAsync(IEnumerable documents) where TDocument : IDocument; - - /// - /// Adds a list of documents to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The document you want to add. - void AddMany(IEnumerable documents) where TDocument : IDocument; - - #endregion - - #region Create TKey - - /// - /// Asynchronously adds a document to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to add. - Task AddOneAsync(TDocument document) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Adds a document to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to add. - void AddOne(TDocument document) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Asynchronously adds a list of documents to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The documents you want to add. - Task AddManyAsync(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Adds a list of documents to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The documents you want to add. - void AddMany(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable; - - #endregion - - #region Update - - /// - /// Asynchronously Updates a document. - /// - /// The type representing a Document. - /// The document with the modifications you want to persist. - Task UpdateOneAsync(TDocument modifiedDocument) where TDocument : IDocument; - - /// - /// Updates a document. - /// - /// The type representing a Document. - /// The document with the modifications you want to persist. - bool UpdateOne(TDocument modifiedDocument) where TDocument : IDocument; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - bool UpdateOne(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument; - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The document you want to modify. - /// The update definition for the document. - Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument; - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The document you want to modify. - /// The update definition for the document. - bool UpdateOne(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument; - - #endregion - - #region Update TKey - - /// - /// Asynchronously Updates a document. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document with the modifications you want to persist. - Task UpdateOneAsync(TDocument modifiedDocument) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Updates a document. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document with the modifications you want to persist. - bool UpdateOne(TDocument modifiedDocument) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to modify. - /// The update definition for the document. - Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to modify. - /// The update definition for the document. - bool UpdateOne(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// For the entity selected by the filter, updates the property field with the given value.. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - bool UpdateOne(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - #endregion - - #region Delete - - /// - /// Asynchronously deletes a document. - /// - /// The type representing a Document. - /// The document you want to delete. - /// The number of documents deleted. - Task DeleteOneAsync(TDocument document) where TDocument : IDocument; - - /// - /// Asynchronously deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - Task DeleteOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Deletes a document. - /// - /// The type representing a Document. - /// The document you want to delete. - /// The number of documents deleted. - long DeleteOne(TDocument document) where TDocument : IDocument; - - /// - /// Deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - long DeleteOne(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - Task DeleteManyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously deletes a list of documents. - /// - /// The type representing a Document. - /// The list of documents to delete. - /// The number of documents deleted. - Task DeleteManyAsync(IEnumerable documents) where TDocument : IDocument; - - /// - /// Deletes a list of documents. - /// - /// The type representing a Document. - /// The list of documents to delete. - /// The number of documents deleted. - long DeleteMany(IEnumerable documents) where TDocument : IDocument; - - /// - /// Deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - long DeleteMany(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - #endregion - - #region Delete TKey - - /// - /// Deletes a document. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to delete. - /// The number of documents deleted. - long DeleteOne(TDocument document) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Asynchronously deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to delete. - /// The number of documents deleted. - Task DeleteOneAsync(TDocument document) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - long DeleteOne(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Asynchronously deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - Task DeleteOneAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - Task DeleteManyAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Asynchronously deletes a list of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The list of documents to delete. - /// The number of documents deleted. - Task DeleteManyAsync(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Deletes a list of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The list of documents to delete. - /// The number of documents deleted. - long DeleteMany(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - long DeleteMany(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - - #endregion - - #region Project - - /// - /// Asynchronously returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class; - - /// - /// Asynchronously returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class; - - /// - /// Returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class; - - /// - /// Returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class; - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class; - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class; - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class; - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// - /// The projection expression. - /// An optional partition key. - List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class; - - #endregion - /// /// Asynchronously returns a paginated list of the documents matching the filter condition. /// @@ -654,45 +65,6 @@ namespace MongoDbGenericRepository Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) where TDocument : IDocument where TKey : IEquatable; - - #region Grouping - - /// - /// Groups a collection of documents given a grouping criteria, - /// and returns a list of projected documents. - /// - /// The type representing a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - List GroupBy( - Expression> groupingCriteria, - Expression, TProjection>> groupProjection, - string partitionKey = null) - where TDocument : IDocument - where TProjection : class, new(); - - /// - /// Groups filtered a collection of documents given a grouping criteria, - /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. - /// - /// The type representing a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - List GroupBy(Expression> filter, - Expression> selector, - Expression, TProjection>> projection, - string partitionKey = null) - where TDocument : IDocument - where TProjection : class, new(); - - #endregion } } diff --git a/MongoDbGenericRepository/Abstractions/IBaseReadOnlyRepository.cs b/MongoDbGenericRepository/Abstractions/IBaseReadOnlyRepository.cs new file mode 100644 index 0000000..32d5c92 --- /dev/null +++ b/MongoDbGenericRepository/Abstractions/IBaseReadOnlyRepository.cs @@ -0,0 +1,410 @@ +using MongoDB.Driver; +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 + + #region Project TKey + + /// + /// Asynchronously returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// + /// The projection expression. + /// An optional partition key. + Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class; + + /// + /// Returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// + /// The projection expression. + /// An optional partition key. + TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class; + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// + /// The projection expression. + /// An optional partition key. + Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class; + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// + /// The projection expression. + /// An optional partition key. + List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class; + + #endregion + + #region Group By + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new(); + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + List GroupBy( + Expression> filter, + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new(); + + #endregion Group By + } +} diff --git a/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.TKey.cs similarity index 71% rename from MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs rename to MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.TKey.cs index a2b42c1..7790fc8 100644 --- a/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.TKey.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using MongoDB.Driver; @@ -7,8 +8,7 @@ using MongoDbGenericRepository.Models; namespace MongoDbGenericRepository { - public interface IKeyTypedReadOnlyMongoRepository : IBaseReadOnlyRepository - where TKey : IEquatable + public interface IReadOnlyMongoRepository where TKey : IEquatable { #region Read @@ -242,5 +242,98 @@ namespace MongoDbGenericRepository where TDocument : IDocument; #endregion Maths + + #region Project + + /// + /// Asynchronously returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TProjection : class; + + /// + /// Returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TProjection : class; + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TProjection : class; + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TProjection : class; + + #endregion Project + + #region Group By + + /// + /// Groups a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new(); + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + List GroupBy( + Expression> filter, + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new(); + + #endregion Group By } } \ No newline at end of file diff --git a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs index a5e295e..e36e8bd 100644 --- a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs @@ -1,11 +1,16 @@ -using System; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; namespace MongoDbGenericRepository { /// /// The IReadOnlyMongoRepository exposes the readonly functionality of the BaseMongoRepository. /// - public interface IReadOnlyMongoRepository : IBaseReadOnlyRepository, IKeyTypedReadOnlyMongoRepository + public interface IReadOnlyMongoRepository : IBaseReadOnlyRepository, IReadOnlyMongoRepository { + } } diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs b/MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs deleted file mode 100644 index 440e143..0000000 --- a/MongoDbGenericRepository/BaseMongoDbRepository.IndexManagement.cs +++ /dev/null @@ -1,176 +0,0 @@ -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 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 BaseMongoRepository : ReadOnlyMongoRepository, IBaseMongoRepository - { - #region Index Management - - /// - public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - { - return await CreateTextIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Indexes - .CreateOneAsync( - new CreateIndexModel( - Builders.IndexKeys.Text(field), - indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions) - )); - } - - /// - public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument - { - return await CreateAscendingIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var indexKey = Builders.IndexKeys; - return await collection.Indexes - .CreateOneAsync( - new CreateIndexModel(indexKey.Ascending(field), createOptions)); - } - - /// - public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - { - return await CreateDescendingIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var indexKey = Builders.IndexKeys; - return await collection.Indexes - .CreateOneAsync( - new CreateIndexModel(indexKey.Descending(field), createOptions)); - } - - /// - public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - { - return await CreateHashedIndexAsync(field, indexCreationOptions, partitionKey); - } - - /// - public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var indexKey = Builders.IndexKeys; - return await collection.Indexes - .CreateOneAsync( - new CreateIndexModel(indexKey.Hashed(field), createOptions)); - } - - /// - public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument - { - return await CreateCombinedTextIndexAsync(fields, indexCreationOptions, partitionKey); - } - - /// - public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = HandlePartitioned(partitionKey); - var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); - var listOfDefs = new List>(); - foreach (var field in fields) - { - listOfDefs.Add(Builders.IndexKeys.Text(field)); - } - return await collection.Indexes - .CreateOneAsync(new CreateIndexModel(Builders.IndexKeys.Combine(listOfDefs), createOptions)); - } - - /// - public async Task DropIndexAsync(string indexName, string partitionKey = null) - where TDocument : IDocument - { - await DropIndexAsync(indexName, partitionKey); - } - - /// - public async Task DropIndexAsync(string indexName, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - await HandlePartitioned(partitionKey).Indexes.DropOneAsync(indexName); - } - - /// - public async Task> GetIndexesNamesAsync(string partitionKey = null) - where TDocument : IDocument - { - return await GetIndexesNamesAsync(partitionKey); - } - - /// - public async Task> GetIndexesNamesAsync(string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var indexCursor = await HandlePartitioned(partitionKey).Indexes.ListAsync(); - var indexes = await indexCursor.ToListAsync(); - return indexes.Select(e => e["name"].ToString()).ToList(); - } - - - #endregion Index Management - - private CreateIndexOptions MapIndexOptions(IndexCreationOptions indexCreationOptions) - { - return new CreateIndexOptions - { - Unique = indexCreationOptions.Unique, - TextIndexVersion = indexCreationOptions.TextIndexVersion, - SphereIndexVersion = indexCreationOptions.SphereIndexVersion, - Sparse = indexCreationOptions.Sparse, - Name = indexCreationOptions.Name, - Min = indexCreationOptions.Min, - Max = indexCreationOptions.Max, - LanguageOverride = indexCreationOptions.LanguageOverride, - ExpireAfter = indexCreationOptions.ExpireAfter, - DefaultLanguage = indexCreationOptions.DefaultLanguage, - BucketSize = indexCreationOptions.BucketSize, - Bits = indexCreationOptions.Bits, - Background = indexCreationOptions.Background, - Version = indexCreationOptions.Version - }; - } - } -} \ No newline at end of file diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs deleted file mode 100644 index db9dd3d..0000000 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ /dev/null @@ -1,1156 +0,0 @@ -using MongoDB.Driver; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Linq.Expressions; -using MongoDbGenericRepository.Models; -using System.Linq; -using MongoDbGenericRepository.Utils; - -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 BaseMongoRepository : ReadOnlyMongoRepository, IBaseMongoRepository - { - /// - /// 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 BaseMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) - { - } - - /// - /// The contructor taking a . - /// - /// A mongodb context implementing - protected BaseMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) - { - } - - /// - /// The contructor taking a . - /// - /// A mongodb context implementing - protected BaseMongoRepository(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 - - #region Create TKey - - /// - /// Asynchronously adds a document to the collection. - /// Populates the Id and AddedAtUtc fields if necessary. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to add. - public virtual async Task AddOneAsync(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - 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 type of the primary key for a Document. - /// The document you want to add. - public virtual void AddOne(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - 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 type of the primary key for a Document. - /// The documents you want to add. - public virtual async Task AddManyAsync(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable - { - 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 type of the primary key for a Document. - /// The documents you want to add. - public virtual void AddMany(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable - { - 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 - - #region Update - - /// - /// Asynchronously Updates a document. - /// - /// The type representing a Document. - /// The document with the modifications you want to persist. - public virtual async Task UpdateOneAsync(TDocument modifiedDocument) where TDocument : IDocument - { - var updateRes = await HandlePartitioned(modifiedDocument).ReplaceOneAsync(x => x.Id == modifiedDocument.Id, modifiedDocument); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates a document. - /// - /// The type representing a Document. - /// The document with the modifications you want to persist. - public virtual bool UpdateOne(TDocument modifiedDocument) where TDocument : IDocument - { - var updateRes = HandlePartitioned(modifiedDocument).ReplaceOne(x => x.Id == modifiedDocument.Id, modifiedDocument); - return updateRes.ModifiedCount == 1; - } - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The document you want to modify. - /// The update definition for the document. - public virtual async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, update); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - public virtual bool UpdateOne(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - public virtual async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - public virtual bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - var updateRes = collection.UpdateOne(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - public virtual bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - var updateRes = collection.UpdateOne(Builders.Filter.Where(filter), Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - public virtual async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - var updateRes = await collection.UpdateOneAsync(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - public virtual async Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - var updateRes = await collection.UpdateOneAsync(Builders.Filter.Where(filter), Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The document you want to modify. - /// The update definition for the document. - public virtual bool UpdateOne(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, update, new UpdateOptions { IsUpsert = true }); - return updateRes.ModifiedCount == 1; - } - - #endregion Update - - #region Update TKey - - /// - /// Asynchronously Updates a document. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document with the modifications you want to persist. - public virtual async Task UpdateOneAsync(TDocument modifiedDocument) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", modifiedDocument.Id); - var updateRes = await HandlePartitioned(modifiedDocument).ReplaceOneAsync(filter, modifiedDocument); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates a document. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document with the modifications you want to persist. - public virtual bool UpdateOne(TDocument modifiedDocument) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", modifiedDocument.Id); - var updateRes = HandlePartitioned(modifiedDocument).ReplaceOne(filter, modifiedDocument); - return updateRes.ModifiedCount == 1; - } - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to modify. - /// The update definition for the document. - public virtual async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); - return updateRes.ModifiedCount == 1; - } - - /// - /// Takes a document you want to modify and applies the update you have defined in MongoDb. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to modify. - /// The update definition for the document. - public virtual bool UpdateOne(TDocument documentToModify, UpdateDefinition update) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, update, new UpdateOptions { IsUpsert = true }); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - public virtual async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document you want to modify. - /// The field selector. - /// The new value of the property field. - public virtual bool UpdateOne(TDocument documentToModify, Expression> field, TField value) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", documentToModify.Id); - var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// Updates the property field with the given value update a property field in entities. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - public virtual async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - var updateRes = await collection.UpdateOneAsync(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - public virtual async Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await UpdateOneAsync(Builders.Filter.Where(filter), field, value, partitionKey); - } - - /// - /// Updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The value of the partition key. - public virtual bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - var updateRes = collection.UpdateOne(filter, Builders.Update.Set(field, value)); - return updateRes.ModifiedCount == 1; - } - - /// - /// For the entity selected by the filter, updates the property field with the given value. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type of the field. - /// The document filter. - /// The field selector. - /// The new value of the property field. - /// The partition key for the document. - public virtual bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return UpdateOne(Builders.Filter.Where(filter), field, value, partitionKey); - } - - #endregion Update - - #region Delete - - /// - /// Asynchronously deletes a document. - /// - /// The type representing a Document. - /// The document you want to delete. - /// The number of documents deleted. - public virtual async Task DeleteOneAsync(TDocument document) where TDocument : IDocument - { - return await DeleteOneAsync(document); - } - - /// - /// Deletes a document. - /// - /// The type representing a Document. - /// The document you want to delete. - /// The number of documents deleted. - public virtual long DeleteOne(TDocument document) where TDocument : IDocument - { - return DeleteOne(document); - } - - /// - /// Deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual long DeleteOne(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return DeleteOne(filter, partitionKey); - } - - /// - /// Asynchronously deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await DeleteOneAsync(filter, partitionKey); - } - - /// - /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual async Task DeleteManyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return (await HandlePartitioned(partitionKey).DeleteManyAsync(filter)).DeletedCount; - } - - /// - /// Asynchronously deletes a list of documents. - /// - /// The type representing a Document. - /// The list of documents to delete. - /// The number of documents deleted. - public virtual async Task DeleteManyAsync(IEnumerable documents) where TDocument : IDocument - { - return await DeleteManyAsync(documents); - } - - /// - /// Deletes a list of documents. - /// - /// The type representing a Document. - /// The list of documents to delete. - /// The number of documents deleted. - public virtual long DeleteMany(IEnumerable documents) where TDocument : IDocument - { - return DeleteMany(documents); - } - - /// - /// Deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual long DeleteMany(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).DeleteMany(filter).DeletedCount; - } - - #endregion Delete - - #region Delete TKey - - /// - /// Deletes a document. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to delete. - /// The number of documents deleted. - public virtual long DeleteOne(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", document.Id); - return HandlePartitioned(document).DeleteOne(filter).DeletedCount; - } - - /// - /// Asynchronously deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The document you want to delete. - /// The number of documents deleted. - public virtual async Task DeleteOneAsync(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", document.Id); - return (await HandlePartitioned(document).DeleteOneAsync(filter)).DeletedCount; - } - - /// - /// Deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual long DeleteOne(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).DeleteOne(filter).DeletedCount; - } - - /// - /// Asynchronously deletes a document matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return (await HandlePartitioned(partitionKey).DeleteOneAsync(filter)).DeletedCount; - } - - /// - /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual async Task DeleteManyAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return (await HandlePartitioned(partitionKey).DeleteManyAsync(filter)).DeletedCount; - } - - /// - /// Asynchronously deletes a list of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The list of documents to delete. - /// The number of documents deleted. - public virtual async Task DeleteManyAsync(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable - { - if (!documents.Any()) - { - return 0; - } - // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 - if (documents.Any(e => e is IPartitionedDocument)) - { - long deleteCount = 0; - foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) - { - var groupIdsTodelete = group.Select(e => e.Id).ToArray(); - deleteCount += (await HandlePartitioned(group.FirstOrDefault()).DeleteManyAsync(x => groupIdsTodelete.Contains(x.Id))).DeletedCount; - } - return deleteCount; - } - else - { - var idsTodelete = documents.Select(e => e.Id).ToArray(); - return (await HandlePartitioned(documents.FirstOrDefault()).DeleteManyAsync(x => idsTodelete.Contains(x.Id))).DeletedCount; - } - } - - /// - /// Deletes a list of documents. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The list of documents to delete. - /// The number of documents deleted. - public virtual long DeleteMany(IEnumerable documents) - where TDocument : IDocument - where TKey : IEquatable - { - if (!documents.Any()) - { - return 0; - } - // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 - if (documents.Any(e => e is IPartitionedDocument)) - { - long deleteCount = 0; - foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) - { - var groupIdsTodelete = group.Select(e => e.Id).ToArray(); - deleteCount += (HandlePartitioned(group.FirstOrDefault()).DeleteMany(x => groupIdsTodelete.Contains(x.Id))).DeletedCount; - } - return deleteCount; - } - else - { - var idsTodelete = documents.Select(e => e.Id).ToArray(); - return (HandlePartitioned(documents.FirstOrDefault()).DeleteMany(x => idsTodelete.Contains(x.Id))).DeletedCount; - } - } - - /// - /// Deletes the documents matching the condition of the LINQ expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public virtual long DeleteMany(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).DeleteMany(filter).DeletedCount; - } - - #endregion - - #region Project - - /// - /// Asynchronously returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual async Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class - { - return await HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .FirstOrDefaultAsync(); - } - - /// - /// Asynchronously returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual async Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class - { - return await HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .FirstOrDefaultAsync(); - } - - /// - /// Returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class - { - return HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .FirstOrDefault(); - } - - /// - /// Returns a projected document matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class - { - return HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .FirstOrDefault(); - } - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual async Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class - { - return await HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .ToListAsync(); - } - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual async Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class - { - return await HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .ToListAsync(); - } - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type representing the model you want to project to. - /// A LINQ expression filter. - /// The projection expression. - /// An optional partition key. - public virtual List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TProjection : class - { - return HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .ToList(); - } - - /// - /// Asynchronously returns a list of projected documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The type representing the model you want to project to. - /// The document filter. - /// The projection expression. - /// An optional partition key. - public virtual List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - where TProjection : class - { - return HandlePartitioned(partitionKey).Find(filter) - .Project(projection) - .ToList(); - } - - #endregion - - #region Grouping - - /// - /// Groups a collection of documents given a grouping criteria, - /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. - /// - /// The type representing a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - public virtual List GroupBy( - Expression> groupingCriteria, - Expression, TProjection>> groupProjection, - string partitionKey = null) - where TDocument : IDocument - where TProjection : class, new() - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - return collection.Aggregate() - .Group(groupingCriteria, groupProjection) - .ToList(); - - } - - /// - /// Groups filtered a collection of documents given a grouping criteria, - /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. - /// - /// The type representing a Document. - /// The type of the grouping criteria. - /// The type of the projected group. - /// A LINQ expression filter. - /// The grouping criteria. - /// The projected group result. - /// The partition key of your document, if any. - public virtual List GroupBy(Expression> filter, - Expression> selector, - Expression, TProjection>> projection, - string partitionKey = null) - where TDocument : IDocument - where TProjection : class, new() - { - var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); - return collection.Aggregate() - .Match(Builders.Filter.Where(filter)) - .Group(selector, projection) - .ToList(); - } - - - #endregion - - /// - /// Asynchronously returns a paginated list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The property selector. - /// Order of the sorting. - /// The number of documents you want to skip. Default value is 0. - /// The number of documents you want to take. Default value is 50. - /// An optional partition key. - public virtual async Task> GetSortedPaginatedAsync( - Expression> filter, - Expression> sortSelector, - bool ascending = true, - int skipNumber = 0, - int takeNumber = 50, - string partitionKey = null) - where TDocument : IDocument - { - var sorting = ascending - ? Builders.Sort.Ascending(sortSelector) - : Builders.Sort.Descending(sortSelector); - - return await HandlePartitioned(partitionKey) - .Find(filter) - .Sort(sorting) - .Skip(skipNumber) - .Limit(takeNumber) - .ToListAsync(); - } - - - /// - /// Asynchronously returns a paginated list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The number of documents you want to skip. Default value is 0. - /// The number of documents you want to take. Default value is 50. - /// An optional partition key. - public virtual async Task> GetPaginatedAsync( - Expression> filter, - int skipNumber = 0, - int takeNumber = 50, - string partitionKey = null) - where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).Find(filter).Skip(skipNumber).Limit(takeNumber).ToListAsync(); - } - - /// - /// Asynchronously returns a paginated list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// The number of documents you want to skip. Default value is 0. - /// The number of documents you want to take. Default value is 50. - /// An optional partition key. - public virtual async Task> GetPaginatedAsync(Expression> filter, int skipNumber = 0, int takeNumber = 50, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Find(filter).Skip(skipNumber).Limit(takeNumber).ToListAsync(); - } - - #region Find And Update - - /// - /// GetAndUpdateOne with filter - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// - /// - /// - public virtual async Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) where TDocument : IDocument - { - return await GetCollection().FindOneAndUpdateAsync(filter, update, options); - } - - /// - /// GetAndUpdateOne with filter - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// - /// - /// - public virtual async Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection().FindOneAndUpdateAsync(filter, update, options); - } - - #endregion Find And Update - - /// - /// Sets the value of the document Id if it is not set already. - /// - /// The document type. - /// The type of the primary key. - /// The document. - protected void FormatDocument(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - 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(); - } - } - - /// - /// 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)); - } - if (document.Id == default(Guid)) - { - document.Id = Guid.NewGuid(); - } - } - } -} \ No newline at end of file diff --git a/MongoDbGenericRepository/BaseMongoRepository.Create.cs b/MongoDbGenericRepository/BaseMongoRepository.Create.cs new file mode 100644 index 0000000..5d9db5a --- /dev/null +++ b/MongoDbGenericRepository/BaseMongoRepository.Create.cs @@ -0,0 +1,186 @@ +using MongoDbGenericRepository.DataAccess.Create; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Create : IBaseMongoRepository_Create + { + /// + /// Asynchronously adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to add. + Task AddOneAsync(TDocument document) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to add. + void AddOne(TDocument document) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Asynchronously adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The documents you want to add. + Task AddManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The documents you want to add. + void AddMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable; + } + + /// + /// 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 BaseMongoRepository : IBaseMongoRepository_Create + { + private readonly object _initLock = new object(); + private MongoDbCreator _mongoDbCreator; + protected MongoDbCreator MongoDbCreator + { + get + { + if (_mongoDbCreator != null) { return _mongoDbCreator; } + + lock (_initLock) + { + if (_mongoDbCreator == null) + { + _mongoDbCreator = new MongoDbCreator(MongoDbContext); + } + } + + return _mongoDbCreator; + } + } + + /// + /// Asynchronously adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to add. + public virtual async Task AddOneAsync(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + await MongoDbCreator.AddOneAsync(document); + } + + /// + /// 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 + { + await MongoDbCreator.AddOneAsync(document); + } + + /// + /// Adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to add. + public virtual void AddOne(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + MongoDbCreator.AddOne(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 + { + MongoDbCreator.AddOne(document); + } + + /// + /// Asynchronously adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The documents you want to add. + public virtual async Task AddManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + await MongoDbCreator.AddManyAsync(documents); + } + + /// + /// 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 + { + await MongoDbCreator.AddManyAsync(documents); + } + + /// + /// Adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The documents you want to add. + public virtual void AddMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + MongoDbCreator.AddMany(documents); + } + + /// + /// 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 + { + MongoDbCreator.AddMany(documents); + } + } + +} diff --git a/MongoDbGenericRepository/BaseMongoRepository.Delete.cs b/MongoDbGenericRepository/BaseMongoRepository.Delete.cs new file mode 100644 index 0000000..0c0491a --- /dev/null +++ b/MongoDbGenericRepository/BaseMongoRepository.Delete.cs @@ -0,0 +1,343 @@ +using MongoDbGenericRepository.DataAccess.Delete; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Delete : IBaseMongoRepository_Delete + { + /// + /// Deletes a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + long DeleteOne(TDocument document) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + Task DeleteOneAsync(TDocument document) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + long DeleteOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + Task DeleteOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + Task DeleteManyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Asynchronously deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + Task DeleteManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + long DeleteMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + long DeleteMany(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + } + + public abstract partial class BaseMongoRepository : IBaseMongoRepository_Delete + { + private MongoDbEraser _mongoDbEraser; + protected MongoDbEraser MongoDbEraser + { + get + { + if (_mongoDbEraser != null) { return _mongoDbEraser; } + + lock (_initLock) + { + if (_mongoDbEraser == null) + { + _mongoDbEraser = new MongoDbEraser(MongoDbContext); + } + } + + return _mongoDbEraser; + } + } + + #region Delete + + /// + /// Asynchronously deletes a document. + /// + /// The type representing a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(TDocument document) where TDocument : IDocument + { + return await MongoDbEraser.DeleteOneAsync(document); + } + + /// + /// Deletes a document. + /// + /// The type representing a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual long DeleteOne(TDocument document) where TDocument : IDocument + { + return MongoDbEraser.DeleteOne(document); + } + + /// + /// Deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteOne(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return MongoDbEraser.DeleteOne(filter, partitionKey); + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await MongoDbEraser.DeleteOneAsync(filter, partitionKey); + } + + /// + /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await MongoDbEraser.DeleteManyAsync(filter, partitionKey); + } + + /// + /// Asynchronously deletes a list of documents. + /// + /// The type representing a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(IEnumerable documents) where TDocument : IDocument + { + return await DeleteManyAsync(documents); + } + + /// + /// Deletes a list of documents. + /// + /// The type representing a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual long DeleteMany(IEnumerable documents) where TDocument : IDocument + { + return DeleteMany(documents); + } + + /// + /// Deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteMany(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return MongoDbEraser.DeleteMany(filter, partitionKey); + } + + #endregion Delete + + #region Delete TKey + + /// + /// Deletes a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual long DeleteOne(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbEraser.DeleteOne(document); + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbEraser.DeleteOneAsync(document); + } + + /// + /// Deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbEraser.DeleteOne(filter, partitionKey); + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbEraser.DeleteOneAsync(filter, partitionKey); + } + + /// + /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbEraser.DeleteManyAsync(filter, partitionKey); + } + + /// + /// Asynchronously deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbEraser.DeleteManyAsync(documents); + } + + /// + /// Deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual long DeleteMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbEraser.DeleteMany(documents); + } + + /// + /// Deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteMany(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbEraser.DeleteMany(filter, partitionKey); + } + + #endregion + + } +} diff --git a/MongoDbGenericRepository/BaseMongoRepository.Index.cs b/MongoDbGenericRepository/BaseMongoRepository.Index.cs new file mode 100644 index 0000000..9cdb64b --- /dev/null +++ b/MongoDbGenericRepository/BaseMongoRepository.Index.cs @@ -0,0 +1,319 @@ +using MongoDbGenericRepository.DataAccess.Index; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq.Expressions; +using MongoDbGenericRepository.Models; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Index : IBaseMongoRepository_Index + { + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates an index on the given field in ascending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates an index on the given field in descending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates a hashed index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Creates a combined text index. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The fields we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Drops the index given a field name + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The name of the index + /// An optional partition key + Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + } + /// + /// 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 BaseMongoRepository : IBaseMongoRepository_Index + { + private MongoDbIndexHandler _mongoDbIndexHandler; + protected MongoDbIndexHandler MongoDbIndexHandler + { + get + { + if (_mongoDbIndexHandler != null) { return _mongoDbIndexHandler; } + + lock (_initLock) + { + if (_mongoDbIndexHandler == null) + { + _mongoDbIndexHandler = new MongoDbIndexHandler(MongoDbContext); + } + } + return _mongoDbIndexHandler; + } + } + + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + public async Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.GetIndexesNamesAsync(partitionKey); + } + + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + public async virtual Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbIndexHandler.GetIndexesNamesAsync(partitionKey); + } + + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateTextIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbIndexHandler.CreateTextIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates an index on the given field in ascending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateAscendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates an index on the given field in ascending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbIndexHandler.CreateAscendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates an index on the given field in descending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateDescendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + public async virtual Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbIndexHandler.CreateDescendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates a hashed index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateHashedIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + public async virtual Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbIndexHandler.CreateHashedIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates a combined text index. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The fields we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateCombinedTextIndexAsync(fields, indexCreationOptions, partitionKey); + } + + /// + public async virtual Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbIndexHandler.CreateCombinedTextIndexAsync(fields, indexCreationOptions, partitionKey); + } + + /// + /// Drops the index given a field name + /// + /// The type representing a Document. + /// The name of the index + /// An optional partition key + public async Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + { + await MongoDbIndexHandler.DropIndexAsync(indexName, partitionKey); + } + + /// + public async virtual Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + await MongoDbIndexHandler.DropIndexAsync(indexName, partitionKey); + } + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/BaseMongoRepository.Main.cs b/MongoDbGenericRepository/BaseMongoRepository.Main.cs new file mode 100644 index 0000000..b7df9cc --- /dev/null +++ b/MongoDbGenericRepository/BaseMongoRepository.Main.cs @@ -0,0 +1,211 @@ +using MongoDB.Driver; +using MongoDbGenericRepository.Models; +using MongoDbGenericRepository.Utils; +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 partial class BaseMongoRepository : ReadOnlyMongoRepository, IBaseMongoRepository + { + /// + /// 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 BaseMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected BaseMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected BaseMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + { + } + + + /// + /// Asynchronously returns a paginated list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The property selector. + /// Order of the sorting. + /// The number of documents you want to skip. Default value is 0. + /// The number of documents you want to take. Default value is 50. + /// An optional partition key. + public virtual async Task> GetSortedPaginatedAsync( + Expression> filter, + Expression> sortSelector, + bool ascending = true, + int skipNumber = 0, + int takeNumber = 50, + string partitionKey = null) + where TDocument : IDocument + { + var sorting = ascending + ? Builders.Sort.Ascending(sortSelector) + : Builders.Sort.Descending(sortSelector); + + return await HandlePartitioned(partitionKey) + .Find(filter) + .Sort(sorting) + .Skip(skipNumber) + .Limit(takeNumber) + .ToListAsync(); + } + + + /// + /// Asynchronously returns a paginated list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The number of documents you want to skip. Default value is 0. + /// The number of documents you want to take. Default value is 50. + /// An optional partition key. + public virtual async Task> GetPaginatedAsync( + Expression> filter, + int skipNumber = 0, + int takeNumber = 50, + string partitionKey = null) + where TDocument : IDocument + { + return await HandlePartitioned(partitionKey).Find(filter).Skip(skipNumber).Limit(takeNumber).ToListAsync(); + } + + /// + /// Asynchronously returns a paginated list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// The number of documents you want to skip. Default value is 0. + /// The number of documents you want to take. Default value is 50. + /// An optional partition key. + public virtual async Task> GetPaginatedAsync(Expression> filter, int skipNumber = 0, int takeNumber = 50, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey).Find(filter).Skip(skipNumber).Limit(takeNumber).ToListAsync(); + } + + #region Find And Update + + /// + /// GetAndUpdateOne with filter + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// + /// + /// + public virtual async Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) where TDocument : IDocument + { + return await GetCollection().FindOneAndUpdateAsync(filter, update, options); + } + + /// + /// GetAndUpdateOne with filter + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// + /// + /// + public virtual async Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetCollection().FindOneAndUpdateAsync(filter, update, options); + } + + #endregion Find And Update + + /// + /// Sets the value of the document Id if it is not set already. + /// + /// The document type. + /// The type of the primary key. + /// The document. + protected void FormatDocument(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + 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(); + } + } + + /// + /// 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)); + } + if (document.Id == default(Guid)) + { + document.Id = Guid.NewGuid(); + } + } + + /// + /// 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 collection partition key. + /// + protected virtual IMongoCollection GetCollection(string partitionKey = null) + where TDocument : IDocument + { + return MongoDbContext.GetCollection(partitionKey); + } + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/BaseMongoRepository.Update.cs b/MongoDbGenericRepository/BaseMongoRepository.Update.cs new file mode 100644 index 0000000..4a89323 --- /dev/null +++ b/MongoDbGenericRepository/BaseMongoRepository.Update.cs @@ -0,0 +1,457 @@ +using MongoDB.Driver; +using MongoDbGenericRepository.DataAccess.Update; +using MongoDbGenericRepository.Models; +using System; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Update : IBaseMongoRepository_Update + { + /// + /// Asynchronously Updates a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document with the modifications you want to persist. + Task UpdateOneAsync(TDocument modifiedDocument) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document with the modifications you want to persist. + bool UpdateOne(TDocument modifiedDocument) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// For the entity selected by the filter, updates the property field with the given value.. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + } + /// + /// 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 BaseMongoRepository : IBaseMongoRepository_Update + { + private MongoDbUpdater _mongoDbUpdater; + protected MongoDbUpdater MongoDbUpdater + { + get + { + if (_mongoDbUpdater != null) { return _mongoDbUpdater; } + + lock (_initLock) + { + if (_mongoDbUpdater == null) + { + _mongoDbUpdater = new MongoDbUpdater(MongoDbContext); + } + } + + return _mongoDbUpdater; + } + } + + #region Update + + /// + /// Asynchronously Updates a document. + /// + /// The type representing a Document. + /// The document with the modifications you want to persist. + public virtual async Task UpdateOneAsync(TDocument modifiedDocument) where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(modifiedDocument); + } + + /// + /// Updates a document. + /// + /// The type representing a Document. + /// The document with the modifications you want to persist. + public virtual bool UpdateOne(TDocument modifiedDocument) where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(modifiedDocument); + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(documentToModify, update); + + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(documentToModify, update); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(documentToModify, field, value); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(documentToModify, field, value); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(filter, field, value, partitionKey); + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(filter, field, value, partitionKey); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(filter, field, value, partitionKey); + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual async Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(filter, field, value, partitionKey); + } + + #endregion Update + + #region Update TKey + + /// + /// Asynchronously Updates a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document with the modifications you want to persist. + public virtual async Task UpdateOneAsync(TDocument modifiedDocument) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbUpdater.UpdateOneAsync(modifiedDocument); + } + + /// + /// Updates a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document with the modifications you want to persist. + public virtual bool UpdateOne(TDocument modifiedDocument) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbUpdater.UpdateOne(modifiedDocument); + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbUpdater.UpdateOneAsync(documentToModify, update); + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbUpdater.UpdateOne(documentToModify, update); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbUpdater.UpdateOne(documentToModify, field, value); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbUpdater.UpdateOneAsync(documentToModify, field, value); + } + + /// + /// Updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbUpdater.UpdateOne(filter, field, value, partitionKey); + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbUpdater.UpdateOne(filter, field, value, partitionKey); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbUpdater.UpdateOneAsync(filter, field, value, partitionKey); + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual async Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbUpdater.UpdateOneAsync(Builders.Filter.Where(filter), field, value, partitionKey); + } + + #endregion Update + } + +} diff --git a/MongoDbGenericRepository/BaseRepository.cs b/MongoDbGenericRepository/BaseRepository.cs deleted file mode 100644 index 823c1f8..0000000 --- a/MongoDbGenericRepository/BaseRepository.cs +++ /dev/null @@ -1,843 +0,0 @@ -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/DataAccess/Base/DataAccessBase.cs b/MongoDbGenericRepository/DataAccess/Base/DataAccessBase.cs new file mode 100644 index 0000000..f7a4949 --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Base/DataAccessBase.cs @@ -0,0 +1,158 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.Models; +using System; +using System.Linq; +using System.Linq.Expressions; + +namespace MongoDbGenericRepository.DataAccess.Base +{ + public class DataAccessBase + { + protected IMongoDbContext MongoDbContext; + + public DataAccessBase(IMongoDbContext mongoDbContext) + { + MongoDbContext = mongoDbContext; + } + + #region Utility Methods + + public virtual 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. + /// + public 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. + /// + public 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. + /// + public 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 virtual 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); + } + + /// + /// Maps a IndexCreationOptions object to a MongoDB.Driver.CreateIndexOptions object + /// + /// The options for creating an index. + /// + protected virtual CreateIndexOptions MapIndexOptions(IndexCreationOptions indexCreationOptions) + { + return new CreateIndexOptions + { + Unique = indexCreationOptions.Unique, + TextIndexVersion = indexCreationOptions.TextIndexVersion, + SphereIndexVersion = indexCreationOptions.SphereIndexVersion, + Sparse = indexCreationOptions.Sparse, + Name = indexCreationOptions.Name, + Min = indexCreationOptions.Min, + Max = indexCreationOptions.Max, + LanguageOverride = indexCreationOptions.LanguageOverride, + ExpireAfter = indexCreationOptions.ExpireAfter, + DefaultLanguage = indexCreationOptions.DefaultLanguage, + BucketSize = indexCreationOptions.BucketSize, + Bits = indexCreationOptions.Bits, + Background = indexCreationOptions.Background, + Version = indexCreationOptions.Version + }; + } + + + /// + /// 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. + protected virtual 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. + protected virtual 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); + } + + + #endregion + } +} diff --git a/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs b/MongoDbGenericRepository/DataAccess/Create/MongoDbCreator.cs similarity index 54% rename from MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs rename to MongoDbGenericRepository/DataAccess/Create/MongoDbCreator.cs index 88d6f25..bc490c7 100644 --- a/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/DataAccess/Create/MongoDbCreator.cs @@ -1,4 +1,6 @@ using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Base; using MongoDbGenericRepository.Models; using MongoDbGenericRepository.Utils; using System; @@ -6,52 +8,29 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace MongoDbGenericRepository +namespace MongoDbGenericRepository.DataAccess.Create { - /// - /// 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 + public class MongoDbCreator : DataAccessBase { - /// - /// 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) + public MongoDbCreator(IMongoDbContext mongoDbContext) : base(mongoDbContext) { } - /// - /// 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 + #region Create TKey /// /// Asynchronously adds a document to the collection. /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. + /// The type of the primary key for a Document. /// The document you want to add. - public virtual async Task AddOneAsync(TDocument document) where TDocument : IDocument + public virtual async Task AddOneAsync(TDocument document) + where TDocument : IDocument + where TKey : IEquatable { - FormatDocument(document); - await HandlePartitioned(document).InsertOneAsync(document); + FormatDocument(document); + await HandlePartitioned(document).InsertOneAsync(document); } /// @@ -59,11 +38,14 @@ namespace MongoDbGenericRepository /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. + /// The type of the primary key for a Document. /// The document you want to add. - public virtual void AddOne(TDocument document) where TDocument : IDocument + public virtual void AddOne(TDocument document) + where TDocument : IDocument + where TKey : IEquatable { - FormatDocument(document); - HandlePartitioned(document).InsertOne(document); + FormatDocument(document); + HandlePartitioned(document).InsertOne(document); } /// @@ -71,8 +53,11 @@ namespace MongoDbGenericRepository /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. + /// The type of the primary key for a Document. /// The documents you want to add. - public virtual async Task AddManyAsync(IEnumerable documents) where TDocument : IDocument + public virtual async Task AddManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable { if (!documents.Any()) { @@ -80,19 +65,19 @@ namespace MongoDbGenericRepository } foreach (var document in documents) { - FormatDocument(document); + 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()); + await HandlePartitioned(group.FirstOrDefault()).InsertManyAsync(group.ToList()); } } else { - await GetCollection().InsertManyAsync(documents.ToList()); + await GetCollection().InsertManyAsync(documents.ToList()); } } @@ -101,8 +86,11 @@ namespace MongoDbGenericRepository /// Populates the Id and AddedAtUtc fields if necessary. /// /// The type representing a Document. + /// The type of the primary key for a Document. /// The documents you want to add. - public virtual void AddMany(IEnumerable documents) where TDocument : IDocument + public virtual void AddMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable { if (!documents.Any()) { @@ -110,30 +98,33 @@ namespace MongoDbGenericRepository } foreach (var document in documents) { - FormatDocument(document); + 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()); + HandlePartitioned(group.FirstOrDefault()).InsertMany(group.ToList()); } } else { - GetCollection().InsertMany(documents.ToList()); + GetCollection().InsertMany(documents.ToList()); } } - #endregion Create + #endregion /// /// Sets the value of the document Id if it is not set already. /// /// The document type. + /// The type of the primary key. /// The document. - protected void FormatDocument(TDocument document) where TDocument : IDocument + protected void FormatDocument(TDocument document) + where TDocument : IDocument + where TKey : IEquatable { if (document == null) { diff --git a/MongoDbGenericRepository/DataAccess/Delete/MongoDbEraser.cs b/MongoDbGenericRepository/DataAccess/Delete/MongoDbEraser.cs new file mode 100644 index 0000000..1daabac --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Delete/MongoDbEraser.cs @@ -0,0 +1,180 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Base; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository.DataAccess.Delete +{ + public class MongoDbEraser : DataAccessBase + { + public MongoDbEraser(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + #region Delete TKey + + /// + /// Deletes a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual long DeleteOne(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", document.Id); + return HandlePartitioned(document).DeleteOne(filter).DeletedCount; + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", document.Id); + return (await HandlePartitioned(document).DeleteOneAsync(filter)).DeletedCount; + } + + /// + /// Deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return HandlePartitioned(partitionKey).DeleteOne(filter).DeletedCount; + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return (await HandlePartitioned(partitionKey).DeleteOneAsync(filter)).DeletedCount; + } + + /// + /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return (await HandlePartitioned(partitionKey).DeleteManyAsync(filter)).DeletedCount; + } + + /// + /// Asynchronously deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + if (!documents.Any()) + { + return 0; + } + // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 + if (documents.Any(e => e is IPartitionedDocument)) + { + long deleteCount = 0; + foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) + { + var groupIdsTodelete = group.Select(e => e.Id).ToArray(); + deleteCount += (await HandlePartitioned(group.FirstOrDefault()).DeleteManyAsync(x => groupIdsTodelete.Contains(x.Id))).DeletedCount; + } + return deleteCount; + } + else + { + var idsTodelete = documents.Select(e => e.Id).ToArray(); + return (await HandlePartitioned(documents.FirstOrDefault()).DeleteManyAsync(x => idsTodelete.Contains(x.Id))).DeletedCount; + } + } + + /// + /// Deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual long DeleteMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + if (!documents.Any()) + { + return 0; + } + // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 + if (documents.Any(e => e is IPartitionedDocument)) + { + long deleteCount = 0; + foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) + { + var groupIdsTodelete = group.Select(e => e.Id).ToArray(); + deleteCount += (HandlePartitioned(group.FirstOrDefault()).DeleteMany(x => groupIdsTodelete.Contains(x.Id))).DeletedCount; + } + return deleteCount; + } + else + { + var idsTodelete = documents.Select(e => e.Id).ToArray(); + return (HandlePartitioned(documents.FirstOrDefault()).DeleteMany(x => idsTodelete.Contains(x.Id))).DeletedCount; + } + } + + /// + /// Deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteMany(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return HandlePartitioned(partitionKey).DeleteMany(filter).DeletedCount; + } + + #endregion + + } +} diff --git a/MongoDbGenericRepository/DataAccess/Index/MongoDbIndexHandler.cs b/MongoDbGenericRepository/DataAccess/Index/MongoDbIndexHandler.cs new file mode 100644 index 0000000..6662670 --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Index/MongoDbIndexHandler.cs @@ -0,0 +1,167 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Base; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository.DataAccess.Index +{ + public class MongoDbIndexHandler : DataAccessBase + { + public MongoDbIndexHandler(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + public async virtual Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var indexCursor = await HandlePartitioned(partitionKey).Indexes.ListAsync(); + var indexes = await indexCursor.ToListAsync(); + return indexes.Select(e => e["name"].ToString()).ToList(); + } + + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await HandlePartitioned(partitionKey).Indexes + .CreateOneAsync( + new CreateIndexModel( + Builders.IndexKeys.Text(field), + indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions) + )); + } + + /// + /// Creates an index on the given field in ascending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var indexKey = Builders.IndexKeys; + return await collection.Indexes + .CreateOneAsync( + new CreateIndexModel(indexKey.Ascending(field), createOptions)); + } + + /// + /// Creates an index on the given field in descending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var indexKey = Builders.IndexKeys; + return await collection.Indexes + .CreateOneAsync( + new CreateIndexModel(indexKey.Descending(field), createOptions)); + } + + /// + /// Creates a hashed index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var indexKey = Builders.IndexKeys; + return await collection.Indexes + .CreateOneAsync( + new CreateIndexModel(indexKey.Hashed(field), createOptions)); + } + + /// + /// Creates a combined text index. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The fields we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = HandlePartitioned(partitionKey); + var createOptions = indexCreationOptions == null ? null : MapIndexOptions(indexCreationOptions); + var listOfDefs = new List>(); + foreach (var field in fields) + { + listOfDefs.Add(Builders.IndexKeys.Text(field)); + } + return await collection.Indexes + .CreateOneAsync(new CreateIndexModel(Builders.IndexKeys.Combine(listOfDefs), createOptions)); + } + + /// + /// Drops the index given a field name + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The name of the index + /// An optional partition key + public async virtual Task DropIndexAsync(string indexName, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + await HandlePartitioned(partitionKey).Indexes.DropOneAsync(indexName); + } + } +} diff --git a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs new file mode 100644 index 0000000..1282efd --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Main.cs @@ -0,0 +1,448 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Base; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository.DataAccess.Read +{ + public partial class MongoDbReader : DataAccessBase + { + public MongoDbReader(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + #region Read TKey + + /// + /// Asynchronously returns one document given its id. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The Id of the document you want to get. + /// An optional partition key. + public async virtual 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 virtual 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 virtual 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 virtual 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 virtual 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 virtual 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 virtual 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 virtual 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 virtual 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 virtual 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 virtual long Count(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + } + + #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. + public async virtual 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 virtual 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 virtual 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 virtual 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 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 virtual 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 virtual 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 Min / Max + + #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 Sum TKey + } + + public partial class MongoDbReader + { + /// + /// Groups a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public virtual List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + return HandlePartitioned(partitionKey) + .Aggregate() + .Group(groupingCriteria, groupProjection) + .ToList(); + + } + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public virtual List GroupBy( + Expression> filter, + Expression> selector, + Expression, TProjection>> projection, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + var collection = HandlePartitioned(partitionKey); + return collection.Aggregate() + .Match(Builders.Filter.Where(filter)) + .Group(selector, projection) + .ToList(); + } + } +} diff --git a/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs new file mode 100644 index 0000000..3499a66 --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Read/MongoDbReader.Project.cs @@ -0,0 +1,90 @@ +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.DataAccess.Read +{ + public partial class MongoDbReader + { + /// + /// Asynchronously returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual async Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return await HandlePartitioned(partitionKey).Find(filter) + .Project(projection) + .FirstOrDefaultAsync(); + } + + /// + /// Returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return HandlePartitioned(partitionKey).Find(filter) + .Project(projection) + .FirstOrDefault(); + } + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual async Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return await HandlePartitioned(partitionKey).Find(filter) + .Project(projection) + .ToListAsync(); + } + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// The document filter. + /// The projection expression. + /// An optional partition key. + public virtual List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return HandlePartitioned(partitionKey).Find(filter) + .Project(projection) + .ToList(); + } + } +} diff --git a/MongoDbGenericRepository/DataAccess/Update/MongoDbUpdater.cs b/MongoDbGenericRepository/DataAccess/Update/MongoDbUpdater.cs new file mode 100644 index 0000000..0657132 --- /dev/null +++ b/MongoDbGenericRepository/DataAccess/Update/MongoDbUpdater.cs @@ -0,0 +1,190 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Base; +using MongoDbGenericRepository.Models; +using MongoDbGenericRepository.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository.DataAccess.Update +{ + public class MongoDbUpdater : DataAccessBase + { + public MongoDbUpdater(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// Asynchronously Updates a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document with the modifications you want to persist. + public virtual async Task UpdateOneAsync(TDocument modifiedDocument) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", modifiedDocument.Id); + var updateRes = await HandlePartitioned(modifiedDocument).ReplaceOneAsync(filter, modifiedDocument); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document with the modifications you want to persist. + public virtual bool UpdateOne(TDocument modifiedDocument) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", modifiedDocument.Id); + var updateRes = HandlePartitioned(modifiedDocument).ReplaceOne(filter, modifiedDocument); + return updateRes.ModifiedCount == 1; + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true }); + return updateRes.ModifiedCount == 1; + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, update, new UpdateOptions { IsUpsert = true }); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = await HandlePartitioned(documentToModify).UpdateOneAsync(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + where TKey : IEquatable + { + var filter = Builders.Filter.Eq("Id", documentToModify.Id); + var updateRes = HandlePartitioned(documentToModify).UpdateOne(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + var updateRes = await collection.UpdateOneAsync(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual async Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await UpdateOneAsync(Builders.Filter.Where(filter), field, value, partitionKey); + } + + /// + /// Updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + var collection = string.IsNullOrEmpty(partitionKey) ? GetCollection() : GetCollection(partitionKey); + var updateRes = collection.UpdateOne(filter, Builders.Update.Set(field, value)); + return updateRes.ModifiedCount == 1; + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return UpdateOne(Builders.Filter.Where(filter), field, value, partitionKey); + } + } +} diff --git a/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Create.cs b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Create.cs new file mode 100644 index 0000000..216f47f --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Create.cs @@ -0,0 +1,114 @@ +using MongoDbGenericRepository.DataAccess.Create; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Create where TKey : IEquatable + { + /// + /// 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. + Task AddOneAsync(TDocument document) where TDocument : IDocument; + + /// + /// 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. + void AddOne(TDocument document) where TDocument : IDocument; + + /// + /// 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. + Task AddManyAsync(IEnumerable documents) where TDocument : IDocument; + + /// + /// 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. + void AddMany(IEnumerable documents) where TDocument : IDocument; + } + + /// + /// 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 BaseMongoRepository : IBaseMongoRepository_Create where TKey : IEquatable + { + protected MongoDbCreator _mongoDbCreator; + protected MongoDbCreator MongoDbCreator + { + get + { + if(_mongoDbCreator == null) + { + lock (_initLock) + { + if(_mongoDbCreator == null) + { + _mongoDbCreator = new MongoDbCreator(MongoDbContext); + } + } + } + return _mongoDbCreator; + } + } + + /// + /// 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 + { + await MongoDbCreator.AddOneAsync(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 + { + MongoDbCreator.AddOne(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 + { + await MongoDbCreator.AddManyAsync(documents); + } + + /// + /// 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 + { + MongoDbCreator.AddMany(documents); + } + } +} diff --git a/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Delete.cs b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Delete.cs new file mode 100644 index 0000000..d6d3097 --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Delete.cs @@ -0,0 +1,226 @@ +using MongoDbGenericRepository.DataAccess.Delete; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Delete where TKey : IEquatable + { + /// + /// Deletes a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + long DeleteOne(TDocument document) + where TDocument : IDocument; + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + Task DeleteOneAsync(TDocument document) + where TDocument : IDocument; + + /// + /// Deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + long DeleteOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + Task DeleteOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + Task DeleteManyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Asynchronously deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + Task DeleteManyAsync(IEnumerable documents) + where TDocument : IDocument; + + /// + /// Deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + long DeleteMany(IEnumerable documents) + where TDocument : IDocument; + + /// + /// Deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + long DeleteMany(Expression> filter, string partitionKey = null) + where TDocument : IDocument; + } + + public abstract partial class BaseMongoRepository: IBaseMongoRepository_Delete + where TKey : IEquatable + { + private MongoDbEraser _mongoDbEraser; + protected MongoDbEraser MongoDbEraser + { + get + { + if (_mongoDbEraser != null) { return _mongoDbEraser; } + + lock (_initLock) + { + if (_mongoDbEraser == null) + { + _mongoDbEraser = new MongoDbEraser(MongoDbContext); + } + } + return _mongoDbEraser; + } + } + + /// + /// Deletes a document. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual long DeleteOne(TDocument document) + where TDocument : IDocument + { + return MongoDbEraser.DeleteOne(document); + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The document you want to delete. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(TDocument document) + where TDocument : IDocument + { + return await MongoDbEraser.DeleteOneAsync(document); + } + + /// + /// Deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + { + return MongoDbEraser.DeleteOne(filter, partitionKey); + } + + /// + /// Asynchronously deletes a document matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbEraser.DeleteOneAsync(filter, partitionKey); + } + + /// + /// Asynchronously deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbEraser.DeleteManyAsync(filter, partitionKey); + } + + /// + /// Asynchronously deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual async Task DeleteManyAsync(IEnumerable documents) + where TDocument : IDocument + { + return await MongoDbEraser.DeleteManyAsync(documents); + } + + /// + /// Deletes a list of documents. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The list of documents to delete. + /// The number of documents deleted. + public virtual long DeleteMany(IEnumerable documents) + where TDocument : IDocument + { + return MongoDbEraser.DeleteMany(documents); + } + + /// + /// Deletes the documents matching the condition of the LINQ expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public virtual long DeleteMany(Expression> filter, string partitionKey = null) + where TDocument : IDocument + { + return MongoDbEraser.DeleteMany(filter, partitionKey); + } + } +} diff --git a/MongoDbGenericRepository/Abstractions/IMongoDbCollectionIndexRepository.cs b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Index.cs similarity index 69% rename from MongoDbGenericRepository/Abstractions/IMongoDbCollectionIndexRepository.cs rename to MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Index.cs index 01c0add..1807ab2 100644 --- a/MongoDbGenericRepository/Abstractions/IMongoDbCollectionIndexRepository.cs +++ b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Index.cs @@ -1,4 +1,5 @@ -using MongoDbGenericRepository.Models; +using MongoDbGenericRepository.DataAccess.Index; +using MongoDbGenericRepository.Models; using System; using System.Collections.Generic; using System.Linq.Expressions; @@ -6,11 +7,17 @@ using System.Threading.Tasks; namespace MongoDbGenericRepository { - /// - /// The repository interface for managing indexes - /// - public interface IMongoDbCollectionIndexRepository + public interface IBaseMongoRepository_Index where TKey : IEquatable { + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument; + /// /// Create a text index on the given field. /// IndexCreationOptions can be supplied to further specify @@ -22,22 +29,7 @@ namespace MongoDbGenericRepository /// An optional partition key. /// The result of the create index operation. Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Create a text index on the given field. - /// IndexCreationOptions can be supplied to further specify - /// how the creation should be done. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index. - /// Options for creating an index. - /// An optional partition key. - /// The result of the create index operation. - Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; + where TDocument : IDocument; /// /// Creates an index on the given field in ascending order. @@ -49,22 +41,8 @@ namespace MongoDbGenericRepository /// Options for creating an index. /// An optional partition key. /// The result of the create index operation. - Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) where TDocument : IDocument; - - /// - /// Creates an index on the given field in ascending order. - /// IndexCreationOptions can be supplied to further specify - /// how the creation should be done. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index. - /// Options for creating an index. - /// An optional partition key. - /// The result of the create index operation. - Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; + Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument; /// /// Creates an index on the given field in descending order. @@ -75,24 +53,9 @@ namespace MongoDbGenericRepository /// The field we want to index. /// Options for creating an index. /// An optional partition key. - /// A string containing the result of the operation. + /// The result of the create index operation. Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Creates an index on the given field in descending order. - /// IndexCreationOptions can be supplied to further specify - /// how the creation should be done. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index. - /// Options for creating an index. - /// An optional partition key. - /// The result of the create index operation. - Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; + where TDocument : IDocument; /// /// Creates a hashed index on the given field. @@ -103,24 +66,9 @@ namespace MongoDbGenericRepository /// The field we want to index. /// Options for creating an index. /// An optional partition key. - /// A string containing the result of the operation. + /// The result of the create index operation. Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Creates a hashed index on the given field. - /// IndexCreationOptions can be supplied to further specify - /// how the creation should be done. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The field we want to index. - /// Options for creating an index. - /// An optional partition key. - /// The result of the create index operation. - Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; + where TDocument : IDocument; /// /// Creates a combined text index. @@ -133,22 +81,7 @@ namespace MongoDbGenericRepository /// An optional partition key. /// The result of the create index operation. Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Creates a combined text index. - /// IndexCreationOptions can be supplied to further specify - /// how the creation should be done. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The fields we want to index. - /// Options for creating an index. - /// An optional partition key. - /// The result of the create index operation. - Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; + where TDocument : IDocument; /// /// Drops the index given a field name @@ -157,37 +90,137 @@ namespace MongoDbGenericRepository /// The name of the index /// An optional partition key Task DropIndexAsync(string indexName, string partitionKey = null) - where TDocument : IDocument; + where TDocument : IDocument; + } + + /// + /// 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 BaseMongoRepository : IBaseMongoRepository_Index + where TKey : IEquatable + { + private MongoDbIndexHandler _mongoDbIndexHandler; + protected MongoDbIndexHandler MongoDbIndexHandler + { + get + { + if (_mongoDbIndexHandler != null) { return _mongoDbIndexHandler; } + + lock (_initLock) + { + if (_mongoDbIndexHandler == null) + { + _mongoDbIndexHandler = new MongoDbIndexHandler(MongoDbContext); + } + } + return _mongoDbIndexHandler; + } + } + + /// + /// Returns the names of the indexes present on a collection. + /// + /// The type representing a Document. + /// An optional partition key + /// A list containing the names of the indexes on on the concerned collection. + public async virtual Task> GetIndexesNamesAsync(string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.GetIndexesNamesAsync(partitionKey); + } + + /// + /// Create a text index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateTextIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateTextIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates an index on the given field in ascending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateAscendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateAscendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates an index on the given field in descending order. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateDescendingIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateDescendingIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates a hashed index on the given field. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The field we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateHashedIndexAsync(Expression> field, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateHashedIndexAsync(field, indexCreationOptions, partitionKey); + } + + /// + /// Creates a combined text index. + /// IndexCreationOptions can be supplied to further specify + /// how the creation should be done. + /// + /// The type representing a Document. + /// The fields we want to index. + /// Options for creating an index. + /// An optional partition key. + /// The result of the create index operation. + public async virtual Task CreateCombinedTextIndexAsync(IEnumerable>> fields, IndexCreationOptions indexCreationOptions = null, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbIndexHandler.CreateCombinedTextIndexAsync(fields, indexCreationOptions, partitionKey); + } /// /// Drops the index given a field name /// /// The type representing a Document. - /// The type of the primary key for a Document. /// The name of the index /// An optional partition key - Task DropIndexAsync(string indexName, string partitionKey = null) + public async virtual Task DropIndexAsync(string indexName, string partitionKey = null) where TDocument : IDocument - where TKey : IEquatable; - - /// - /// Returns the names of the indexes present on a collection. - /// - /// The type representing a Document. - /// An optional partition key - /// A list containing the names of the indexes on on the concerned collection. - Task> GetIndexesNamesAsync(string partitionKey = null) - where TDocument : IDocument; - - /// - /// Returns the names of the indexes present on a collection. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// An optional partition key - /// A list containing the names of the indexes on on the concerned collection. - Task> GetIndexesNamesAsync(string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; + { + await MongoDbIndexHandler.DropIndexAsync(indexName, partitionKey); + } } } diff --git a/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Main.cs b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Main.cs new file mode 100644 index 0000000..ef79b46 --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Main.cs @@ -0,0 +1,82 @@ +using MongoDB.Driver; +using MongoDbGenericRepository.Models; +using System; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoDbRepository : + IReadOnlyMongoRepository, + IBaseMongoRepository_Create, + IBaseMongoRepository_Delete, + IBaseMongoRepository_Index, + IBaseMongoRepository_Update + where TKey : IEquatable + { + } + + /// + /// 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 BaseMongoRepository : + ReadOnlyMongoRepository, + IBaseMongoDbRepository + where TKey : IEquatable + { + protected readonly object _initLock = new object(); + + /// + /// 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 BaseMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected BaseMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected BaseMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + { + } + + /// + /// 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 collection partition key. + /// + protected virtual IMongoCollection GetCollection(string partitionKey = null) + where TDocument : IDocument + { + return MongoDbContext.GetCollection(partitionKey); + } + } +} diff --git a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.ReadOnly.cs similarity index 62% rename from MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs rename to MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.ReadOnly.cs index 3f3d37f..a103005 100644 --- a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.ReadOnly.cs @@ -1,5 +1,5 @@ using MongoDB.Driver; -using MongoDB.Driver.Linq; +using MongoDbGenericRepository.DataAccess.Read; using MongoDbGenericRepository.Models; using System; using System.Collections.Generic; @@ -13,14 +13,43 @@ 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 + public abstract partial class ReadOnlyMongoRepository : IReadOnlyMongoRepository where TKey : IEquatable { + /// + /// The connection string. + /// + public string ConnectionString { get; protected set; } + + /// + /// The database name. + /// + public string DatabaseName { get; protected set; } + + /// + /// The MongoDbContext + /// + protected IMongoDbContext MongoDbContext = null; + + /// + /// A MongoDb Reader for read operations + /// + protected MongoDbReader MongoDbReader = 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 KeyTypedReadOnlyMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) + protected ReadOnlyMongoRepository(string connectionString, string databaseName = null) + { + SetupMongoDbContext(connectionString, databaseName); + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : this(new MongoDbContext(mongoDatabase)) { } @@ -28,16 +57,27 @@ namespace MongoDbGenericRepository /// The contructor taking a . /// /// A mongodb context implementing - protected KeyTypedReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) { + SetupMongoDbContext(mongoDbContext); } - /// - /// The contructor taking a . - /// - /// A mongodb context implementing - protected KeyTypedReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + protected void SetupMongoDbContext(IMongoDbContext mongoDbContext) { + MongoDbContext = MongoDbContext ?? mongoDbContext; + MongoDbReader = MongoDbReader ?? new MongoDbReader(MongoDbContext); + } + + protected void SetupMongoDbContext(string connectionString, string databaseName) + { + if (databaseName == null) + { + var mongoUrl = new MongoUrl(connectionString); + databaseName = databaseName ?? mongoUrl.DatabaseName; + } + ConnectionString = connectionString; + DatabaseName = databaseName; + SetupMongoDbContext(new MongoDbContext(connectionString, databaseName)); } #region Read @@ -50,7 +90,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument { - return await base.GetByIdAsync(id, partitionKey); + return await MongoDbReader.GetByIdAsync(id, partitionKey); } /// @@ -61,7 +101,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument { - return base.GetById(id, partitionKey); + return MongoDbReader.GetById(id, partitionKey); } /// @@ -72,7 +112,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await base.GetOneAsync(filter, partitionKey); + return await MongoDbReader.GetOneAsync(filter, partitionKey); } /// @@ -83,7 +123,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return base.GetOne(filter, partitionKey); + return MongoDbReader.GetOne(filter, partitionKey); } /// @@ -94,7 +134,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return base.GetCursor(filter, partitionKey); + return MongoDbReader.GetCursor(filter, partitionKey); } /// @@ -105,7 +145,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await base.AnyAsync(filter, partitionKey); + return await MongoDbReader.AnyAsync(filter, partitionKey); } /// @@ -116,7 +156,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return base.Any(filter, partitionKey); + return MongoDbReader.Any(filter, partitionKey); } /// @@ -127,7 +167,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await base.GetAllAsync(filter, partitionKey); + return await MongoDbReader.GetAllAsync(filter, partitionKey); } /// @@ -138,7 +178,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return base.GetAll(filter, partitionKey); + return MongoDbReader.GetAll(filter, partitionKey); } /// @@ -149,7 +189,7 @@ namespace MongoDbGenericRepository /// An optional partitionKey public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await base.CountAsync(filter, partitionKey); + return await MongoDbReader.CountAsync(filter, partitionKey); } /// @@ -160,7 +200,7 @@ namespace MongoDbGenericRepository /// An optional partitionKey public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return base.Count(filter, partitionKey); + return MongoDbReader.Count(filter, partitionKey); } /// @@ -173,7 +213,7 @@ namespace MongoDbGenericRepository public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return await base.GetByMaxAsync(filter, maxValueSelector, partitionKey); + return await MongoDbReader.GetByMaxAsync(filter, maxValueSelector, partitionKey); } /// @@ -187,7 +227,7 @@ namespace MongoDbGenericRepository public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return base.GetByMax(filter, maxValueSelector, partitionKey); + return MongoDbReader.GetByMax(filter, maxValueSelector, partitionKey); } /// @@ -200,7 +240,7 @@ namespace MongoDbGenericRepository public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return await base.GetByMinAsync(filter, minValueSelector, partitionKey); + return await MongoDbReader.GetByMinAsync(filter, minValueSelector, partitionKey); } /// @@ -213,7 +253,7 @@ namespace MongoDbGenericRepository public TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return base.GetByMin(filter, minValueSelector, partitionKey); + return MongoDbReader.GetByMin(filter, minValueSelector, partitionKey); } /// @@ -227,7 +267,7 @@ namespace MongoDbGenericRepository public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return await base.GetMaxValueAsync(filter, maxValueSelector, partitionKey); + return await MongoDbReader.GetMaxValueAsync(filter, maxValueSelector, partitionKey); } /// @@ -241,7 +281,7 @@ namespace MongoDbGenericRepository public TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return base.GetMaxValue(filter, maxValueSelector, partitionKey); + return MongoDbReader.GetMaxValue(filter, maxValueSelector, partitionKey); } /// @@ -255,7 +295,7 @@ namespace MongoDbGenericRepository public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return await base.GetMinValueAsync(filter, minValueSelector, partitionKey); + return await MongoDbReader.GetMinValueAsync(filter, minValueSelector, partitionKey); } /// @@ -269,7 +309,7 @@ namespace MongoDbGenericRepository public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return base.GetMinValue(filter, minValueSelector, partitionKey); + return MongoDbReader.GetMinValue(filter, minValueSelector, partitionKey); } #endregion @@ -288,7 +328,7 @@ namespace MongoDbGenericRepository string partitionKey = null) where TDocument : IDocument { - return await base.SumByAsync(filter, selector, partitionKey); + return await MongoDbReader.SumByAsync(filter, selector, partitionKey); } /// @@ -303,7 +343,7 @@ namespace MongoDbGenericRepository string partitionKey = null) where TDocument : IDocument { - return await base.SumByAsync(filter, selector, partitionKey); + return await MongoDbReader.SumByAsync(filter, selector, partitionKey); } /// @@ -318,7 +358,7 @@ namespace MongoDbGenericRepository string partitionKey = null) where TDocument : IDocument { - return base.SumBy(filter, selector, partitionKey); + return MongoDbReader.SumBy(filter, selector, partitionKey); } /// @@ -333,58 +373,117 @@ namespace MongoDbGenericRepository string partitionKey = null) where TDocument : IDocument { - return base.SumBy(filter, selector, partitionKey); + return MongoDbReader.SumBy(filter, selector, partitionKey); } #endregion Maths - #region Utility Methods + #region Project /// - /// Gets a collections for the type TDocument with the matching partition key (if any). + /// Asynchronously returns a projected document matching the filter condition. /// - /// The document type. + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. /// An optional partition key. - /// An - protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument + public virtual async Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TProjection : class { - return MongoDbContext.GetCollection(partitionKey); + return await MongoDbReader.ProjectOneAsync(filter, projection, partitionKey); } /// - /// Gets a collections for a potentially partitioned document type. + /// Returns a projected document matching the filter condition. /// - /// The document type. - /// The type of the primary key. - /// The document. - /// - protected virtual IMongoCollection HandlePartitioned(TDocument document) + /// The type representing a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) where TDocument : IDocument + where TProjection : class { - if (document is IPartitionedDocument) - { - return GetCollection(((IPartitionedDocument)document).PartitionKey); - } - return GetCollection(); + return MongoDbReader.ProjectOne(filter, projection, partitionKey); } /// - /// Gets a collections for a potentially partitioned document type. + /// Asynchronously returns a list of projected documents matching the filter condition. /// - /// The document type. - /// The type of the primary key. - /// The collection partition key. - /// - protected virtual IMongoCollection HandlePartitioned(string partitionKey) + /// The type representing a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual async Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) where TDocument : IDocument + where TProjection : class { - if (!string.IsNullOrEmpty(partitionKey)) - { - return GetCollection(partitionKey); - } - return GetCollection(); + return await MongoDbReader.ProjectManyAsync(filter, projection, partitionKey); } - #endregion + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TProjection : class + { + return MongoDbReader.ProjectMany(filter, projection, partitionKey); + } + + + #endregion Project + + /// + /// Groups a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public virtual List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new() + { + return MongoDbReader.GroupBy(groupingCriteria, groupProjection, partitionKey); + } + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public virtual List GroupBy( + Expression> filter, + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TProjection : class, new() + { + return MongoDbReader.GroupBy(filter, groupingCriteria, groupProjection, partitionKey); + } } } \ No newline at end of file diff --git a/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Update.cs b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Update.cs new file mode 100644 index 0000000..8e22067 --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedRepository/BaseMongoRepository.TKey.Update.cs @@ -0,0 +1,269 @@ +using MongoDB.Driver; +using MongoDbGenericRepository.DataAccess.Update; +using MongoDbGenericRepository.Models; +using System; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + public interface IBaseMongoRepository_Update where TKey : IEquatable + { + /// + /// Asynchronously Updates a document. + /// + /// The type representing a Document. + /// The document with the modifications you want to persist. + Task UpdateOneAsync(TDocument modifiedDocument) where TDocument : IDocument; + + /// + /// Updates a document. + /// + /// The type representing a Document. + /// The document with the modifications you want to persist. + bool UpdateOne(TDocument modifiedDocument) where TDocument : IDocument; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument; + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument; + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument; + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument; + } + + public abstract partial class BaseMongoRepository : IBaseMongoRepository_Update + where TKey : IEquatable + { + private MongoDbUpdater _mongoDbUpdater; + protected MongoDbUpdater MongoDbUpdater + { + get + { + if (_mongoDbUpdater != null) { return _mongoDbUpdater; } + + lock (_initLock) + { + if (_mongoDbUpdater == null) + { + _mongoDbUpdater = new MongoDbUpdater(MongoDbContext); + } + } + + return _mongoDbUpdater; + } + } + + /// + /// Asynchronously Updates a document. + /// + /// The type representing a Document. + /// The document with the modifications you want to persist. + public virtual async Task UpdateOneAsync(TDocument modifiedDocument) where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(modifiedDocument); + } + + /// + /// Updates a document. + /// + /// The type representing a Document. + /// The document with the modifications you want to persist. + public virtual bool UpdateOne(TDocument modifiedDocument) where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(modifiedDocument); + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual async Task UpdateOneAsync(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(documentToModify, update); + } + + /// + /// Takes a document you want to modify and applies the update you have defined in MongoDb. + /// + /// The type representing a Document. + /// The document you want to modify. + /// The update definition for the document. + public virtual bool UpdateOne(TDocument documentToModify, UpdateDefinition update) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(documentToModify, update); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual bool UpdateOne(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(documentToModify, field, value); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document you want to modify. + /// The field selector. + /// The new value of the property field. + public virtual async Task UpdateOneAsync(TDocument documentToModify, Expression> field, TField value) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(documentToModify, field, value); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual bool UpdateOne(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(filter, field, value, partitionKey); + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual bool UpdateOne(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return MongoDbUpdater.UpdateOne(filter, field, value, partitionKey); + } + + /// + /// Updates the property field with the given value update a property field in entities. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The value of the partition key. + public virtual async Task UpdateOneAsync(FilterDefinition filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(filter, field, value, partitionKey); + } + + /// + /// For the entity selected by the filter, updates the property field with the given value. + /// + /// The type representing a Document. + /// The type of the field. + /// The document filter. + /// The field selector. + /// The new value of the property field. + /// The partition key for the document. + public virtual async Task UpdateOneAsync(Expression> filter, Expression> field, TField value, string partitionKey = null) + where TDocument : IDocument + { + return await MongoDbUpdater.UpdateOneAsync(filter, field, value, partitionKey); + } + } +} diff --git a/MongoDbGenericRepository/MongoDbContext.cs b/MongoDbGenericRepository/MongoDbContext.cs index c5921b9..a7a5520 100644 --- a/MongoDbGenericRepository/MongoDbContext.cs +++ b/MongoDbGenericRepository/MongoDbContext.cs @@ -21,24 +21,6 @@ namespace MongoDbGenericRepository /// public IMongoDatabase Database { get; } - /// - /// Sets the Guid representation of the MongoDB Driver. - /// - /// The new value of the GuidRepresentation - public virtual void SetGuidRepresentation(MongoDB.Bson.GuidRepresentation guidRepresentation) - { - MongoDefaults.GuidRepresentation = guidRepresentation; - } - - /// - /// Initialize the Guid representation of the MongoDB Driver. - /// Override this method to change the default GuidRepresentation. - /// - protected virtual void InitializeGuidRepresentation() - { - // by default, avoid legacy UUID representation: use Binary 0x04 subtype. - MongoDefaults.GuidRepresentation = MongoDB.Bson.GuidRepresentation.Standard; - } /// /// The constructor of the MongoDbContext, it needs an object implementing . @@ -76,24 +58,12 @@ namespace MongoDbGenericRepository Database = client.GetDatabase(databaseName); } - /// - /// Extracts the CollectionName attribute from the entity type, if any. - /// - /// The type representing a Document. - /// The name of the collection in which the TDocument is stored. - private string GetAttributeCollectionName() - { - return (typeof(TDocument).GetTypeInfo() - .GetCustomAttributes(typeof(CollectionNameAttribute)) - .FirstOrDefault() as CollectionNameAttribute)?.Name; - } - /// /// Returns a collection for a document type. Also handles document types with a partition key. /// /// The type representing a Document. /// The optional value of the partition key. - public IMongoCollection GetCollection(string partitionKey = null) + public virtual IMongoCollection GetCollection(string partitionKey = null) { return Database.GetCollection(GetCollectionName(partitionKey)); } @@ -102,18 +72,49 @@ namespace MongoDbGenericRepository /// Drops a collection, use very carefully. /// /// The type representing a Document. - public void DropCollection(string partitionKey = null) + public virtual void DropCollection(string partitionKey = null) { Database.DropCollection(GetCollectionName(partitionKey)); } + /// + /// Sets the Guid representation of the MongoDB Driver. + /// + /// The new value of the GuidRepresentation + public virtual void SetGuidRepresentation(MongoDB.Bson.GuidRepresentation guidRepresentation) + { + MongoDefaults.GuidRepresentation = guidRepresentation; + } + + /// + /// Extracts the CollectionName attribute from the entity type, if any. + /// + /// The type representing a Document. + /// The name of the collection in which the TDocument is stored. + protected virtual string GetAttributeCollectionName() + { + return (typeof(TDocument).GetTypeInfo() + .GetCustomAttributes(typeof(CollectionNameAttribute)) + .FirstOrDefault() as CollectionNameAttribute)?.Name; + } + + /// + /// Initialize the Guid representation of the MongoDB Driver. + /// Override this method to change the default GuidRepresentation. + /// + protected virtual void InitializeGuidRepresentation() + { + // by default, avoid legacy UUID representation: use Binary 0x04 subtype. + MongoDefaults.GuidRepresentation = MongoDB.Bson.GuidRepresentation.Standard; + } + /// /// 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 name of the collection. - private string GetCollectionName(string partitionKey) + protected virtual string GetCollectionName(string partitionKey) { var collectionName = GetAttributeCollectionName() ?? Pluralize(); if (string.IsNullOrEmpty(partitionKey)) @@ -128,7 +129,7 @@ namespace MongoDbGenericRepository /// /// The type representing a Document. /// The pluralized document name. - private string Pluralize() + protected virtual string Pluralize() { return (typeof(TDocument).Name.Pluralize()).Camelize(); } diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs index fe995a9..c8bcb99 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs @@ -1,5 +1,11 @@ using MongoDB.Driver; +using MongoDbGenericRepository.DataAccess.Read; +using MongoDbGenericRepository.Models; using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; namespace MongoDbGenericRepository { @@ -7,7 +13,7 @@ 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 ReadOnlyMongoRepository : KeyTypedReadOnlyMongoRepository, IReadOnlyMongoRepository + public abstract class ReadOnlyMongoRepository : ReadOnlyMongoRepository, IReadOnlyMongoRepository { /// /// The constructor taking a connection string and a database name. @@ -33,5 +39,534 @@ namespace MongoDbGenericRepository protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(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 virtual Task GetByIdAsync(TKey id, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.GetByIdAsync(id, partitionKey); + } + + /// + /// Returns one document given its id. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The Id of the document you want to get. + /// An optional partition key. + public virtual TDocument GetById(TKey id, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetById(id, partitionKey); + } + + /// + /// 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 virtual Task GetOneAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.GetOneAsync(filter, partitionKey); + } + + /// + /// Returns one document given an expression filter. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + public virtual TDocument GetOne(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetOne(filter, partitionKey); + } + + /// + /// Returns a collection cursor. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + public virtual IFindFluent GetCursor(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetCursor(filter, partitionKey); + } + + /// + /// 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 virtual Task AnyAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.AnyAsync(filter, partitionKey); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + public virtual bool Any(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.Any(filter, partitionKey); + } + + /// + /// 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 virtual Task> GetAllAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.GetAllAsync(filter, partitionKey); + } + + /// + /// Returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partition key. + public virtual List GetAll(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetAll(filter, partitionKey); + } + + /// + /// 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 virtual Task CountAsync(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.CountAsync(filter, partitionKey); + } + + /// + /// Counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// A LINQ expression filter. + /// An optional partitionKey + public virtual long Count(Expression> filter, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.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. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public async virtual Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.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. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public virtual TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetByMax(filter, maxValueSelector, partitionKey); + } + + /// + /// 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 virtual Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.GetByMinAsync(filter, minValueSelector, partitionKey); + } + + /// + /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public virtual TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.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 primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async virtual Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.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. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public virtual TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.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 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 MongoDbReader.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 TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetMinValue(filter, minValueSelector, partitionKey); + } + + #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 MongoDbReader.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 + where TKey : IEquatable + { + return MongoDbReader.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 async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await MongoDbReader.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 decimal SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.SumBy(filter, selector, partitionKey); + } + + #endregion Sum TKey + + #region Project TKey + + /// + /// Asynchronously returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual async Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return await MongoDbReader.ProjectOneAsync(filter, projection, partitionKey); + } + + /// + /// Returns a projected document matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return MongoDbReader.ProjectOne(filter, projection, partitionKey); + } + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// A LINQ expression filter. + /// The projection expression. + /// An optional partition key. + public virtual async Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return await MongoDbReader.ProjectManyAsync(filter, projection, partitionKey); + } + + /// + /// Asynchronously returns a list of projected documents matching the filter condition. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The type representing the model you want to project to. + /// The document filter. + /// The projection expression. + /// An optional partition key. + public virtual List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class + { + return MongoDbReader.ProjectMany(filter, projection, partitionKey); + } + + #endregion Project TKey + + #region Group By TKey + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public virtual List GroupBy( + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + return MongoDbReader.GroupBy(groupingCriteria, groupProjection, partitionKey); + } + + /// + /// Groups filtered a collection of documents given a grouping criteria, + /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. + /// + /// The type representing a Document. + /// The type of the grouping criteria. + /// The type of the projected group. + /// A LINQ expression filter. + /// The grouping criteria. + /// The projected group result. + /// The partition key of your document, if any. + public virtual List GroupBy( + Expression> filter, + Expression> groupingCriteria, + Expression, TProjection>> groupProjection, + string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + where TProjection : class, new() + { + return MongoDbReader.GroupBy(filter, groupingCriteria, groupProjection, partitionKey); + } + + #endregion Group By TKey + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The document. + /// + public virtual IMongoCollection HandlePartitioned(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.HandlePartitioned(document); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + public virtual IMongoCollection HandlePartitioned(string partitionKey) + where TDocument : IDocument + where TKey : IEquatable + { + if (!string.IsNullOrEmpty(partitionKey)) + { + return GetCollection(partitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The document. + /// + public virtual IMongoCollection HandlePartitioned(TDocument document) + where TDocument : IDocument + { + return MongoDbReader.HandlePartitioned(document); + } + + /// + /// Gets a collections for the type TDocument with a partition key. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + public virtual IMongoCollection GetCollection(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbReader.GetCollection(partitionKey); + } } } \ No newline at end of file