diff --git a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs index 3137d90..eb98474 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs @@ -106,6 +106,32 @@ namespace CoreIntegrationTests.Infrastructure Assert.True (2 == count, GetTestName()); } + [Fact] + public void AddManyWithDifferentPartitionKey() + { + // only run this test for tests on documents with partition key + if (!string.IsNullOrEmpty(PartitionKey)) + { + // Arrange + var documents = new List { new T(), new T(), new T(), new T() }; + if(documents.Any(e => e is IPartitionedDocument)) + { + var secondPartitionKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[2]).PartitionKey = secondPartitionKey; + ((IPartitionedDocument)documents[3]).PartitionKey = secondPartitionKey; + // Act + SUT.AddMany(documents); + // Assert + long count = SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); + long secondPartitionCount = SUT.Count(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + // Cleanup second partition + SUT.DeleteMany(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + Assert.True(2 == count, GetTestName()); + Assert.True(2 == secondPartitionCount, GetTestName()); + } + } + } + [Fact] public async Task AddManyAsync() { @@ -121,6 +147,31 @@ namespace CoreIntegrationTests.Infrastructure Assert.True (2 == count, GetTestName()); } + [Fact] + public async Task AddManyAsyncWithDifferentPartitionKey() + { + // only run this test for tests on documents with partition key + if (!string.IsNullOrEmpty(PartitionKey)) + { + // Arrange + var documents = new List { new T(), new T(), new T(), new T() }; + if (documents.Any(e => e is IPartitionedDocument)) + { + var secondPartitionKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[2]).PartitionKey = secondPartitionKey; + ((IPartitionedDocument)documents[3]).PartitionKey = secondPartitionKey; + // Act + await SUT.AddManyAsync(documents); + // Assert + long count = SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); + long secondPartitionCount = SUT.Count(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + // Cleanup second partition + SUT.DeleteMany(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + Assert.True(2 == count, GetTestName()); + Assert.True(2 == secondPartitionCount, GetTestName()); + } + } + } #endregion Add @@ -523,12 +574,25 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}"; var documents = CreateTestDocuments(5); documents.ForEach(e => e.SomeContent = criteria); + var canPartition = !string.IsNullOrEmpty(PartitionKey) && documents.Any(e => e is IPartitionedDocument); + string secondKey = null; + if (canPartition) + { + secondKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[3]).PartitionKey = secondKey; + ((IPartitionedDocument)documents[4]).PartitionKey = secondKey; + } + SUT.AddMany(documents); // Act var result = await SUT.DeleteManyAsync(documents); // Assert Assert.True(5 == result); Assert.False(SUT.Any(e => e.SomeContent == criteria, PartitionKey), GetTestName()); + if (canPartition) + { + Assert.False(SUT.Any(e => e.SomeContent == criteria, secondKey), GetTestName()); + } } [Fact] @@ -553,12 +617,25 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}"; var documents = CreateTestDocuments(5); documents.ForEach(e => e.SomeContent = criteria); + var canPartition = !string.IsNullOrEmpty(PartitionKey) && documents.Any(e => e is IPartitionedDocument); + string secondKey = null; + if (canPartition) + { + secondKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[3]).PartitionKey = secondKey; + ((IPartitionedDocument)documents[4]).PartitionKey = secondKey; + } + SUT.AddMany(documents); // Act var result = SUT.DeleteMany(documents); // Assert Assert.True(5 == result); Assert.False(SUT.Any(e => e.SomeContent == criteria, PartitionKey), GetTestName()); + if (canPartition) + { + Assert.False(SUT.Any(e => e.SomeContent == criteria, secondKey), GetTestName()); + } } #endregion Delete diff --git a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index cc73df6..af0a2b3 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -107,6 +107,32 @@ namespace CoreIntegrationTests.Infrastructure Assert.True (2 == count, GetTestName()); } + [Fact] + public void AddManyWithDifferentPartitionKey() + { + // only run this test for tests on documents with partition key + if (!string.IsNullOrEmpty(PartitionKey)) + { + // Arrange + var documents = new List { new T(), new T(), new T(), new T() }; + if (documents.Any(e => e is IPartitionedDocument)) + { + var secondPartitionKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[2]).PartitionKey = secondPartitionKey; + ((IPartitionedDocument)documents[3]).PartitionKey = secondPartitionKey; + // Act + SUT.AddMany(documents); + // Assert + long count = SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); + long secondPartitionCount = SUT.Count(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + // Cleanup second partition + SUT.DeleteMany(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + Assert.True(2 == count, GetTestName()); + Assert.True(2 == secondPartitionCount, GetTestName()); + } + } + } + [Fact] public async Task AddManyAsync() { @@ -122,6 +148,31 @@ namespace CoreIntegrationTests.Infrastructure Assert.True (2 == count, GetTestName()); } + [Fact] + public async Task AddManyAsyncWithDifferentPartitionKey() + { + // only run this test for tests on documents with partition key + if (!string.IsNullOrEmpty(PartitionKey)) + { + // Arrange + var documents = new List { new T(), new T(), new T(), new T() }; + if (documents.Any(e => e is IPartitionedDocument)) + { + var secondPartitionKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[2]).PartitionKey = secondPartitionKey; + ((IPartitionedDocument)documents[3]).PartitionKey = secondPartitionKey; + // Act + await SUT.AddManyAsync(documents); + // Assert + long count = SUT.Count(e => e.Id.Equals(documents[0].Id) || e.Id.Equals(documents[1].Id), PartitionKey); + long secondPartitionCount = SUT.Count(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + // Cleanup second partition + SUT.DeleteMany(e => e.Id.Equals(documents[2].Id) || e.Id.Equals(documents[3].Id), secondPartitionKey); + Assert.True(2 == count, GetTestName()); + Assert.True(2 == secondPartitionCount, GetTestName()); + } + } + } #endregion Add @@ -524,12 +575,25 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}"; var documents = CreateTestDocuments(5); documents.ForEach(e => e.SomeContent = criteria); + var canPartition = !string.IsNullOrEmpty(PartitionKey) && documents.Any(e => e is IPartitionedDocument); + string secondKey = null; + if (canPartition) + { + secondKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[3]).PartitionKey = secondKey; + ((IPartitionedDocument)documents[4]).PartitionKey = secondKey; + } + SUT.AddMany(documents); // Act var result = await SUT.DeleteManyAsync(documents); // Assert Assert.True(5 == result); Assert.False(SUT.Any(e => e.SomeContent == criteria, PartitionKey), GetTestName()); + if (canPartition) + { + Assert.False(SUT.Any(e => e.SomeContent == criteria, secondKey), GetTestName()); + } } [Fact] @@ -554,12 +618,25 @@ namespace CoreIntegrationTests.Infrastructure var criteria = $"{GetTestName()}.{DocumentTypeName}"; var documents = CreateTestDocuments(5); documents.ForEach(e => e.SomeContent = criteria); + var canPartition = !string.IsNullOrEmpty(PartitionKey) && documents.Any(e => e is IPartitionedDocument); + string secondKey = null; + if (canPartition) + { + secondKey = $"{PartitionKey}-2"; + ((IPartitionedDocument)documents[3]).PartitionKey = secondKey; + ((IPartitionedDocument)documents[4]).PartitionKey = secondKey; + } + SUT.AddMany(documents); // Act var result = SUT.DeleteMany(documents); // Assert Assert.True(5 == result); Assert.False(SUT.Any(e => e.SomeContent == criteria, PartitionKey), GetTestName()); + if (canPartition) + { + Assert.False(SUT.Any(e => e.SomeContent == criteria, secondKey), GetTestName()); + } } #endregion Delete diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs index 39cec90..c59b08e 100644 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/BaseMongoDbRepository.cs @@ -82,11 +82,22 @@ namespace MongoDbGenericRepository { return; } - foreach (var doc in documents) + foreach (var document in documents) { - FormatDocument(doc); + 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()); } - await HandlePartitioned(documents.FirstOrDefault()).InsertManyAsync(documents); } /// @@ -105,7 +116,18 @@ namespace MongoDbGenericRepository { FormatDocument(document); } - HandlePartitioned(documents.FirstOrDefault()).InsertMany(documents.ToList()); + // 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 @@ -157,11 +179,22 @@ namespace MongoDbGenericRepository { return; } - foreach (var doc in documents) + foreach (var document in documents) { - FormatDocument(doc); + 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()); } - await HandlePartitioned(documents.FirstOrDefault()).InsertManyAsync(documents); } /// @@ -487,9 +520,7 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable { - 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; + return await UpdateOneAsync(Builders.Filter.Where(filter), field, value, partitionKey); } /// @@ -525,9 +556,7 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable { - 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; + return UpdateOne(Builders.Filter.Where(filter), field, value, partitionKey); } #endregion Update @@ -542,7 +571,7 @@ namespace MongoDbGenericRepository /// The number of documents deleted. public virtual async Task DeleteOneAsync(TDocument document) where TDocument : IDocument { - return (await HandlePartitioned(document).DeleteOneAsync(x => x.Id == document.Id)).DeletedCount; + return await DeleteOneAsync(document); } /// @@ -553,7 +582,7 @@ namespace MongoDbGenericRepository /// The number of documents deleted. public virtual long DeleteOne(TDocument document) where TDocument : IDocument { - return HandlePartitioned(document).DeleteOne(x => x.Id == document.Id).DeletedCount; + return DeleteOne(document); } /// @@ -565,7 +594,7 @@ namespace MongoDbGenericRepository /// The number of documents deleted. public virtual long DeleteOne(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return HandlePartitioned(partitionKey).DeleteOne(filter).DeletedCount; + return DeleteOne(filter, partitionKey); } /// @@ -577,7 +606,7 @@ namespace MongoDbGenericRepository /// The number of documents deleted. public virtual async Task DeleteOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return (await HandlePartitioned(partitionKey).DeleteOneAsync(filter)).DeletedCount; + return await DeleteOneAsync(filter, partitionKey); } /// @@ -600,12 +629,7 @@ namespace MongoDbGenericRepository /// The number of documents deleted. public virtual async Task DeleteManyAsync(IEnumerable documents) where TDocument : IDocument { - 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; + return await DeleteManyAsync(documents); } /// @@ -616,12 +640,7 @@ namespace MongoDbGenericRepository /// The number of documents deleted. public virtual long DeleteMany(IEnumerable documents) where TDocument : IDocument { - if (!documents.Any()) - { - return 0; - } - var idsTodelete = documents.Select(e => e.Id).ToArray(); - return HandlePartitioned(documents.FirstOrDefault()).DeleteMany(x => idsTodelete.Contains(x.Id)).DeletedCount; + return DeleteMany(documents); } /// @@ -730,8 +749,22 @@ namespace MongoDbGenericRepository { return 0; } - var idsTodelete = documents.Select(e => e.Id).ToArray(); - return (await HandlePartitioned(documents.FirstOrDefault()).DeleteManyAsync(x => idsTodelete.Contains(x.Id))).DeletedCount; + // 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; + } } /// @@ -749,8 +782,22 @@ namespace MongoDbGenericRepository { return 0; } - var idsTodelete = documents.Select(e => e.Id).ToArray(); - return HandlePartitioned(documents.FirstOrDefault()).DeleteMany(x => idsTodelete.Contains(x.Id)).DeletedCount; + // 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; + } } ///