diff --git a/IntegrationTests/CreateTKeyPartitionedTests.cs b/IntegrationTests/CreateTKeyPartitionedTests.cs new file mode 100644 index 0000000..4cc8fa2 --- /dev/null +++ b/IntegrationTests/CreateTKeyPartitionedTests.cs @@ -0,0 +1,77 @@ +using IntegrationTests.Infrastructure; +using MongoDB.Bson.Serialization.Attributes; +using MongoDbGenericRepository.Models; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace IntegrationTests +{ + + public class CreateTestsPartitionedTKeyDocument : IDocument, IPartitionedDocument + { + [BsonId] + public Guid Id { get; set; } + public int Version { get; set; } + public CreateTestsPartitionedTKeyDocument() + { + Id = Guid.NewGuid(); + Version = 2; + PartitionKey = "TestPartitionKey"; + } + public string PartitionKey { get; set; } + public string SomeContent { get; set; } + } + + public class CreatePartitionedTKeyTests : BaseMongoDbRepositoryTests + { + [Test] + public void PartitionedAddOne() + { + // Arrange + var document = new CreateTestsPartitionedTKeyDocument(); + // Act + SUT.AddOne(document); + // Assert + long count = SUT.Count(e => e.Id == document.Id, PartitionKey); + Assert.AreEqual(1, count); + } + + [Test] + public async Task PartitionedAddOneAsync() + { + // Arrange + var document = new CreateTestsPartitionedTKeyDocument(); + // Act + await SUT.AddOneAsync(document); + // Assert + long count = SUT.Count(e => e.Id == document.Id, PartitionKey); + Assert.AreEqual(1, count); + } + + [Test] + public void PartitionedAddMany() + { + // Arrange + var documents = new List { new CreateTestsPartitionedTKeyDocument(), new CreateTestsPartitionedTKeyDocument() }; + // Act + SUT.AddMany(documents); + // Assert + long count = SUT.Count(e => e.Id == documents[0].Id || e.Id == documents[1].Id, PartitionKey); + Assert.AreEqual(2, count); + } + + [Test] + public async Task PartitionedAddManyAsync() + { + // Arrange + var documents = new List { new CreateTestsPartitionedTKeyDocument(), new CreateTestsPartitionedTKeyDocument() }; + // Act + await SUT.AddManyAsync(documents); + // Assert + long count = SUT.Count(e => e.Id == documents[0].Id || e.Id == documents[1].Id, PartitionKey); + Assert.AreEqual(2, count); + } + } +} diff --git a/IntegrationTests/CreateTKeyTests.cs b/IntegrationTests/CreateTKeyTests.cs new file mode 100644 index 0000000..f709ba7 --- /dev/null +++ b/IntegrationTests/CreateTKeyTests.cs @@ -0,0 +1,75 @@ +using IntegrationTests.Infrastructure; +using MongoDB.Bson.Serialization.Attributes; +using MongoDbGenericRepository.Models; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace IntegrationTests +{ + public class CreateTestsTKeyDocument : IDocument + { + [BsonId] + public Guid Id { get; set; } + public int Version { get; set; } + public CreateTestsTKeyDocument() + { + Id = Guid.NewGuid(); + Version = 2; + } + public string SomeContent { get; set; } + } + + [TestFixture] + public class CreateTKeyTests : BaseMongoDbRepositoryTests + { + [Test] + public void TKeyAddOne() + { + // Arrange + var document = new CreateTestsTKeyDocument(); + // Act + SUT.AddOne(document); + // Assert + long count = SUT.Count(e => e.Id == document.Id); + Assert.AreEqual(1, count); + } + + [Test] + public async Task TKeyAddOneAsync() + { + // Arrange + var document = new CreateTestsTKeyDocument(); + // Act + await SUT.AddOneAsync(document); + // Assert + long count = SUT.Count(e => e.Id == document.Id); + Assert.AreEqual(1, count); + } + + [Test] + public void TKeyAddMany() + { + // Arrange + var documents = new List { new CreateTestsTKeyDocument(), new CreateTestsTKeyDocument() }; + // Act + SUT.AddMany(documents); + // Assert + long count = SUT.Count(e => e.Id == documents[0].Id || e.Id == documents[1].Id); + Assert.AreEqual(2, count); + } + + [Test] + public async Task TKeyAddManyAsync() + { + // Arrange + var documents = new List { new CreateTestsTKeyDocument(), new CreateTestsTKeyDocument() }; + // Act + await SUT.AddManyAsync(documents); + // Assert + long count = SUT.Count(e => e.Id == documents[0].Id || e.Id == documents[1].Id); + Assert.AreEqual(2, count); + } + } +} diff --git a/IntegrationTests/DeletePartitionedTKeyTests.cs b/IntegrationTests/DeletePartitionedTKeyTests.cs new file mode 100644 index 0000000..b213cb4 --- /dev/null +++ b/IntegrationTests/DeletePartitionedTKeyTests.cs @@ -0,0 +1,137 @@ +using IntegrationTests.Infrastructure; +using MongoDB.Bson.Serialization.Attributes; +using MongoDbGenericRepository.Models; +using NUnit.Framework; +using System; +using System.Threading.Tasks; + +namespace IntegrationTests +{ + public class DeleteTestsPartitionedTKeyDocument : IPartitionedDocument, IDocument + { + [BsonId] + public Guid Id { get; set; } + public int Version { get; set; } + public DeleteTestsPartitionedTKeyDocument() + { + Id = Guid.NewGuid(); + Version = 2; + PartitionKey = "TestPartitionKey"; + } + public string PartitionKey { get; set; } + public string SomeContent { get; set; } + } + + public class DeletePartitionedTKeyTests : BaseMongoDbRepositoryTests + { + [Test] + public void PartitionedDeleteOne() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = SUT.DeleteOne(document); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id, PartitionKey)); + } + + [Test] + public void PartitionedDeleteOneLinq() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = SUT.DeleteOne(e => e.Id == document.Id, PartitionKey); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id, PartitionKey)); + } + + [Test] + public async Task PartitionedDeleteOneAsync() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = await SUT.DeleteOneAsync(document); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id, PartitionKey)); + } + + [Test] + public async Task PartitionedDeleteOneAsyncLinq() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = await SUT.DeleteOneAsync(e => e.Id == document.Id, PartitionKey); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id, PartitionKey)); + } + + [Test] + public async Task PartitionedDeleteManyAsyncLinq() + { + // Arrange + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = "DeleteManyAsyncLinqContent"); + SUT.AddMany(documents); + // Act + var result = await SUT.DeleteManyAsync(e => e.SomeContent == "DeleteManyAsyncLinqContent", PartitionKey); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == "DeleteManyAsyncLinqContent", PartitionKey)); + } + + [Test] + public async Task PartitionedDeleteManyAsync() + { + // Arrange + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = "DeleteManyAsyncLinqContent"); + SUT.AddMany(documents); + // Act + var result = await SUT.DeleteManyAsync(documents); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == "DeleteManyAsyncLinqContent", PartitionKey)); + } + + [Test] + public void PartitionedDeleteManyLinq() + { + // Arrange + var content = "DeleteManyLinqContent"; + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = content); + SUT.AddMany(documents); + // Act + var result = SUT.DeleteMany(e => e.SomeContent == content, PartitionKey); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == content, PartitionKey)); + } + + [Test] + public void PartitionedDeleteMany() + { + // Arrange + var content = "DeleteManyContent"; + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = content); + SUT.AddMany(documents); + // Act + var result = SUT.DeleteMany(documents); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == content, PartitionKey)); + } + } +} diff --git a/IntegrationTests/DeleteTKeyTests.cs b/IntegrationTests/DeleteTKeyTests.cs new file mode 100644 index 0000000..dd90c09 --- /dev/null +++ b/IntegrationTests/DeleteTKeyTests.cs @@ -0,0 +1,135 @@ +using IntegrationTests.Infrastructure; +using MongoDB.Bson.Serialization.Attributes; +using MongoDbGenericRepository.Models; +using NUnit.Framework; +using System; +using System.Threading.Tasks; + +namespace IntegrationTests +{ + public class DeleteTestsTKeyDocument : IDocument + { + [BsonId] + public Guid Id { get; set; } + public int Version { get; set; } + public DeleteTestsTKeyDocument() + { + Id = Guid.NewGuid(); + Version = 2; + } + public string SomeContent { get; set; } + } + + public class DeleteTKeyTests : BaseMongoDbRepositoryTests + { + [Test] + public void DeleteOne() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = SUT.DeleteOne(document); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id)); + } + + [Test] + public void DeleteOneLinq() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = SUT.DeleteOne(e => e.Id == document.Id); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id)); + } + + [Test] + public async Task DeleteOneAsync() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = await SUT.DeleteOneAsync(document); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id)); + } + + [Test] + public async Task DeleteOneAsyncLinq() + { + // Arrange + var document = CreateTestDocument(); + SUT.AddOne(document); + // Act + var result = await SUT.DeleteOneAsync(e => e.Id == document.Id); + // Assert + Assert.AreEqual(1, result); + Assert.IsFalse(SUT.Any(e => e.Id == document.Id)); + } + + [Test] + public async Task DeleteManyAsyncLinq() + { + // Arrange + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = "DeleteManyAsyncLinqContent"); + SUT.AddMany(documents); + // Act + var result = await SUT.DeleteManyAsync(e => e.SomeContent == "DeleteManyAsyncLinqContent"); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == "DeleteManyAsyncLinqContent")); + } + + [Test] + public async Task DeleteManyAsync() + { + // Arrange + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = "DeleteManyAsyncLinqContent"); + SUT.AddMany(documents); + // Act + var result = await SUT.DeleteManyAsync(documents); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == "DeleteManyAsyncLinqContent")); + } + + [Test] + public void DeleteManyLinq() + { + // Arrange + var content = "DeleteManyLinqContent"; + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = content); + SUT.AddMany(documents); + // Act + var result = SUT.DeleteMany(e => e.SomeContent == content); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == content)); + } + + [Test] + public void DeleteMany() + { + // Arrange + var content = "DeleteManyContent"; + var documents = CreateTestDocuments(5); + documents.ForEach(e => e.SomeContent = content); + SUT.AddMany(documents); + // Act + var result = SUT.DeleteMany(documents); + // Assert + Assert.AreEqual(5, result); + Assert.IsFalse(SUT.Any(e => e.SomeContent == content)); + } + } +} diff --git a/IntegrationTests/Infrastructure/BaseMongoDbRepositoryTests.cs b/IntegrationTests/Infrastructure/BaseMongoDbRepositoryTests.cs index 74d358e..1c7b43f 100644 --- a/IntegrationTests/Infrastructure/BaseMongoDbRepositoryTests.cs +++ b/IntegrationTests/Infrastructure/BaseMongoDbRepositoryTests.cs @@ -5,7 +5,7 @@ using System.Configuration; namespace IntegrationTests.Infrastructure { - public class BaseMongoDbRepositoryTests where T : Document, new() + public class BaseMongoDbRepositoryTests where T : class, new() { public T CreateTestDocument() { diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj index 580fb5d..b2bef91 100644 --- a/IntegrationTests/IntegrationTests.csproj +++ b/IntegrationTests/IntegrationTests.csproj @@ -52,7 +52,11 @@ + + + + @@ -60,6 +64,7 @@ + diff --git a/IntegrationTests/ProjectTKeyTests.cs b/IntegrationTests/ProjectTKeyTests.cs new file mode 100644 index 0000000..614892a --- /dev/null +++ b/IntegrationTests/ProjectTKeyTests.cs @@ -0,0 +1,152 @@ +using IntegrationTests.Infrastructure; +using MongoDB.Bson.Serialization.Attributes; +using MongoDbGenericRepository.Models; +using NUnit.Framework; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace IntegrationTests +{ + public class NestedTKey + { + public DateTime SomeDate { get; set; } + } + + public class MyProjectionTKey + { + public DateTime SomeDate { get; set; } + public string SomeContent { get; set; } + } + + public class ProjectTestsTKeyDocument : IDocument + { + [BsonId] + public Guid Id { get; set; } + public int Version { get; set; } + public ProjectTestsTKeyDocument() + { + Id = Guid.NewGuid(); + Version = 2; + Nested = new NestedTKey + { + SomeDate = DateTime.UtcNow + }; + } + public string SomeContent { get; set; } + public NestedTKey Nested { get; set; } + } + + public class ProjectTKeyTests : BaseMongoDbRepositoryTests + { + + + [Test] + public async Task ProjectOneAsync() + { + // Arrange + const string someContent = "ProjectOneAsyncContent"; + var someDate = DateTime.UtcNow; + var document = CreateTestDocument(); + document.SomeContent = someContent; + document.Nested.SomeDate = someDate; + SUT.AddOne(document); + // Act + var result = await SUT.ProjectOneAsync( + x => x.Id == document.Id, + x => new MyProjection + { + SomeContent = x.SomeContent, + SomeDate = x.Nested.SomeDate + }); + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(someContent, result.SomeContent); + Assert.AreEqual(someDate.Minute, result.SomeDate.Minute); + Assert.AreEqual(someDate.Second, result.SomeDate.Second); + } + + [Test] + public void ProjectOne() + { + // Arrange + const string someContent = "ProjectOneContent"; + var someDate = DateTime.UtcNow; + var document = CreateTestDocument(); + document.SomeContent = someContent; + document.Nested.SomeDate = someDate; + SUT.AddOne(document); + // Act + var result = SUT.ProjectOne( + x => x.Id == document.Id, + x => new MyProjection + { + SomeContent = x.SomeContent, + SomeDate = x.Nested.SomeDate + }); + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(someContent, result.SomeContent); + Assert.AreEqual(someDate.Minute, result.SomeDate.Minute); + Assert.AreEqual(someDate.Second, result.SomeDate.Second); + } + + [Test] + public async Task ProjectManyAsync() + { + // Arrange + const string someContent = "ProjectManyAsyncContent"; + var someDate = DateTime.UtcNow; + var document = CreateTestDocuments(5); + document.ForEach(e => + { + e.SomeContent = someContent; + e.Nested.SomeDate = someDate; + }); + + SUT.AddMany(document); + // Act + var result = await SUT.ProjectManyAsync( + x => x.SomeContent == someContent, + x => new MyProjection + { + SomeContent = x.SomeContent, + SomeDate = x.Nested.SomeDate + }); + // Assert + Assert.AreEqual(5, result.Count); + Assert.AreEqual(someContent, result.First().SomeContent); + Assert.AreEqual(someDate.Minute, result.First().SomeDate.Minute); + Assert.AreEqual(someDate.Second, result.First().SomeDate.Second); + } + + [Test] + public void ProjectMany() + { + // Arrange + const string someContent = "ProjectManyContent"; + var someDate = DateTime.UtcNow; + var document = CreateTestDocuments(5); + document.ForEach(e => + { + e.SomeContent = someContent; + e.Nested.SomeDate = someDate; + }); + + SUT.AddMany(document); + // Act + var result = SUT.ProjectMany( + x => x.SomeContent == someContent, + x => new MyProjection + { + SomeContent = x.SomeContent, + SomeDate = x.Nested.SomeDate + }); + // Assert + Assert.AreEqual(5, result.Count); + Assert.AreEqual(someContent, result.First().SomeContent); + Assert.AreEqual(someDate.Minute, result.First().SomeDate.Minute); + Assert.AreEqual(someDate.Second, result.First().SomeDate.Second); + } + } +} diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs index f7f566c..630a535 100644 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/BaseMongoDbRepository.cs @@ -31,6 +31,34 @@ namespace MongoDbGenericRepository /// 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. @@ -42,14 +70,6 @@ namespace MongoDbGenericRepository 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 document you want to add. - void AddOne(TDocument document) where TDocument : IDocument; - /// /// Adds a document to the collection. /// Populates the Id and AddedAtUtc fields if necessary. @@ -66,16 +86,22 @@ namespace MongoDbGenericRepository /// 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; + /// 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 document you want to add. - void AddMany(IEnumerable documents) where TDocument : IDocument; + /// 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 @@ -171,6 +197,134 @@ namespace MongoDbGenericRepository #endregion + #region Read TKey + + /// + /// Asynchronously returns one document given its id. + /// + /// The type representing a Document. + /// The type of the primary key for a Document. + /// The Id of the document you want to get. + /// An optional partition key. + Task GetByIdAsync(Guid 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(Guid 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 Update /// @@ -189,6 +343,30 @@ namespace MongoDbGenericRepository #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; + + #endregion + #region Delete /// @@ -259,6 +437,90 @@ namespace MongoDbGenericRepository /// 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. /// @@ -273,7 +535,8 @@ namespace MongoDbGenericRepository #endregion - #region Project + + #region Project /// /// Asynchronously returns a projected document matching the filter condition. @@ -413,7 +676,7 @@ namespace MongoDbGenericRepository /// /// /// - Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) + Task GetAndUpdateOne(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options) where TDocument : IDocument; /// @@ -485,21 +748,6 @@ namespace MongoDbGenericRepository await HandlePartitioned(document).InsertOneAsync(document); } - /// - /// 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 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. @@ -512,21 +760,6 @@ namespace MongoDbGenericRepository HandlePartitioned(document).InsertOne(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 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. @@ -546,6 +779,59 @@ namespace MongoDbGenericRepository await HandlePartitioned(documents.FirstOrDefault()).InsertManyAsync(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 void AddMany(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return; + } + foreach (var document in documents) + { + FormatDocument(document); + } + HandlePartitioned(documents.FirstOrDefault()).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 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 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. @@ -573,8 +859,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 void AddMany(IEnumerable documents) where TDocument : IDocument + public void AddMany(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable { if (!documents.Any()) { @@ -582,12 +871,13 @@ namespace MongoDbGenericRepository } foreach (var document in documents) { - FormatDocument(document); + FormatDocument(document); } - HandlePartitioned(documents.FirstOrDefault()).InsertMany(documents.ToList()); + HandlePartitioned(documents.FirstOrDefault()).InsertMany(documents.ToList()); } - #endregion Create + + #endregion #region Read @@ -728,7 +1018,8 @@ namespace MongoDbGenericRepository /// The Id of the document you want to get. /// An optional partition key. public async Task GetByIdAsync(Guid id, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", id); return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); @@ -742,7 +1033,8 @@ namespace MongoDbGenericRepository /// The Id of the document you want to get. /// An optional partition key. public TDocument GetById(Guid id, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", id); return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); @@ -756,7 +1048,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public async Task GetOneAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); } @@ -769,7 +1062,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public TDocument GetOne(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); } @@ -782,7 +1076,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public IFindFluent GetCursor(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter); } @@ -795,7 +1090,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public async Task AnyAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { var count = await HandlePartitioned(partitionKey).CountAsync(filter); return (count > 0); @@ -809,7 +1105,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public bool Any(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { var count = HandlePartitioned(partitionKey).Count(filter); return (count > 0); @@ -823,7 +1120,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public async Task> GetAllAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); } @@ -836,7 +1134,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partition key. public List GetAll(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter).ToList(); } @@ -849,7 +1148,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partitionKey public async Task CountAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return await HandlePartitioned(partitionKey).CountAsync(filter); } @@ -862,7 +1162,8 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// An optional partitionKey public long Count(Expression> filter, string partitionKey = null) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter).Count(); } @@ -904,7 +1205,8 @@ namespace MongoDbGenericRepository /// The type of the primary key for a Document. /// The document with the modifications you want to persist. public async Task UpdateOneAsync(TDocument modifiedDocument) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", modifiedDocument.Id); var updateRes = await HandlePartitioned(modifiedDocument).ReplaceOneAsync(filter, modifiedDocument); @@ -918,7 +1220,8 @@ namespace MongoDbGenericRepository /// The type of the primary key for a Document. /// The document with the modifications you want to persist. public bool UpdateOne(TDocument modifiedDocument) - where TDocument : IDocument where TKey : IEquatable + where TDocument : IDocument + where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", modifiedDocument.Id); var updateRes = HandlePartitioned(modifiedDocument).ReplaceOne(filter, modifiedDocument); @@ -1019,6 +1322,116 @@ namespace MongoDbGenericRepository 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. + /// A LINQ expression filter. + /// An optional partition key. + /// The number of documents deleted. + public 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 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 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 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 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 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 async Task DeleteManyAsync(IEnumerable documents) + where TDocument : IDocument + where TKey : IEquatable + { + if (!documents.Any()) + { + return 0; + } + 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. /// @@ -1038,18 +1451,6 @@ namespace MongoDbGenericRepository 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. - /// A LINQ expression filter. - /// An optional partition key. - /// The number of documents deleted. - public long DeleteMany(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).DeleteMany(filter).DeletedCount; - } - /// /// Deletes the documents matching the condition of the LINQ expression filter. /// @@ -1065,7 +1466,7 @@ namespace MongoDbGenericRepository return HandlePartitioned(partitionKey).DeleteMany(filter).DeletedCount; } - #endregion Delete + #endregion #region Project @@ -1223,7 +1624,7 @@ namespace MongoDbGenericRepository /// 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 async Task> GetPaginatedAsync(Expression> filter, int skipNumber = 0, int takeNumber = 50, string partitionKey = null) + public 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(); @@ -1299,7 +1700,7 @@ namespace MongoDbGenericRepository return GetCollection(); } - private IMongoCollection HandlePartitioned(TDocument document) + private IMongoCollection HandlePartitioned(TDocument document) where TDocument : IDocument where TKey : IEquatable { diff --git a/MongoDbGenericRepository/Models/IDocument.cs b/MongoDbGenericRepository/Models/IDocument.cs index 07d25c4..3142dfb 100644 --- a/MongoDbGenericRepository/Models/IDocument.cs +++ b/MongoDbGenericRepository/Models/IDocument.cs @@ -1,4 +1,5 @@ -using System; +using MongoDB.Bson.Serialization.Attributes; +using System; namespace MongoDbGenericRepository.Models { @@ -9,9 +10,10 @@ namespace MongoDbGenericRepository.Models public interface IDocument where TKey : IEquatable { /// - /// The Guid, which must be decorated with the [BsonId] attribute + /// The Primary Key, which must be decorated with the [BsonId] attribute /// if you want the MongoDb C# driver to consider it to be the document ID. /// + [BsonId] TKey Id { get; set; } /// /// A version number, to indicate the version of the schema.