From ba723be738c3ae5a12e6b4fb5512d7c000dac888 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Thu, 4 Apr 2019 23:45:07 +0100 Subject: [PATCH] adding Key typed base repo functionality --- CoreIntegrationTests/CRUDObjectIdTests.cs | 2 +- .../KeyTypedBaseMongoDbRepository.cs | 154 ++++++++++++++++++ .../KeyTypedReadOnlyMongoRepository.cs | 8 +- .../ReadOnlyMongoRepository.TKey.cs | 12 +- .../ReadOnlyMongoRepository.cs | 11 -- 5 files changed, 165 insertions(+), 22 deletions(-) create mode 100644 MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs delete mode 100644 MongoDbGenericRepository/ReadOnlyMongoRepository.cs diff --git a/CoreIntegrationTests/CRUDObjectIdTests.cs b/CoreIntegrationTests/CRUDObjectIdTests.cs index 335043f..8a03de0 100644 --- a/CoreIntegrationTests/CRUDObjectIdTests.cs +++ b/CoreIntegrationTests/CRUDObjectIdTests.cs @@ -1,6 +1,6 @@ using CoreIntegrationTests.Infrastructure; using MongoDB.Bson; -using System; + namespace CoreIntegrationTests { public class CoreObjectIdTestDocument : TestDoc diff --git a/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs b/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs new file mode 100644 index 0000000..0adba7f --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs @@ -0,0 +1,154 @@ +using MongoDB.Driver; +using MongoDbGenericRepository.Models; +using MongoDbGenericRepository.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + /// + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. + /// + /// + public abstract class KeyTypedBaseMongoDbRepository : KeyTypedReadOnlyMongoRepository, IKeyTypedReadOnlyMongoRepository where TKey : IEquatable + { + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected KeyTypedBaseMongoDbRepository(string connectionString, string databaseName) : base(connectionString, databaseName) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedBaseMongoDbRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedBaseMongoDbRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + { + } + + + #region Create + + /// + /// Asynchronously adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The document you want to add. + public virtual async Task AddOneAsync(TDocument document) where TDocument : IDocument + { + FormatDocument(document); + await HandlePartitioned(document).InsertOneAsync(document); + } + + /// + /// Adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The document you want to add. + public virtual void AddOne(TDocument document) where TDocument : IDocument + { + FormatDocument(document); + HandlePartitioned(document).InsertOne(document); + } + + /// + /// Asynchronously adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The documents you want to add. + public virtual async Task AddManyAsync(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return; + } + foreach (var document in documents) + { + FormatDocument(document); + } + // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 + if (documents.Any(e => e is IPartitionedDocument)) + { + foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) + { + await HandlePartitioned(group.FirstOrDefault()).InsertManyAsync(group.ToList()); + } + } + else + { + await GetCollection().InsertManyAsync(documents.ToList()); + } + } + + /// + /// Adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// The type representing a Document. + /// The documents you want to add. + public virtual void AddMany(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return; + } + foreach (var document in documents) + { + FormatDocument(document); + } + // cannot use typeof(IPartitionedDocument).IsAssignableFrom(typeof(TDocument)), not available in netstandard 1.5 + if (documents.Any(e => e is IPartitionedDocument)) + { + foreach (var group in documents.GroupBy(e => ((IPartitionedDocument)e).PartitionKey)) + { + HandlePartitioned(group.FirstOrDefault()).InsertMany(group.ToList()); + } + } + else + { + GetCollection().InsertMany(documents.ToList()); + } + } + + #endregion Create + + + /// + /// Sets the value of the document Id if it is not set already. + /// + /// The document type. + /// The document. + protected void FormatDocument(TDocument document) where TDocument : IDocument + { + if (document == null) + { + throw new ArgumentNullException(nameof(document)); + } + var defaultTKey = default(TKey); + if (document.Id == null + || (defaultTKey != null + && defaultTKey.Equals(document.Id))) + { + document.Id = IdGenerator.GetId(); + } + } + + } +} diff --git a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs index 2f071df..7c41e7e 100644 --- a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs @@ -263,7 +263,7 @@ namespace MongoDbGenericRepository public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey).Project(maxValueSelector).FirstOrDefaultAsync(); + return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey).Project(maxValueSelector).FirstOrDefaultAsync(); } /// @@ -277,7 +277,7 @@ namespace MongoDbGenericRepository public TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetMaxMongoQuery(filter, maxValueSelector, partitionKey).Project(maxValueSelector).FirstOrDefault(); + return GetMaxMongoQuery(filter, maxValueSelector, partitionKey).Project(maxValueSelector).FirstOrDefault(); } /// @@ -291,7 +291,7 @@ namespace MongoDbGenericRepository public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); + return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); } /// @@ -305,7 +305,7 @@ namespace MongoDbGenericRepository public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); + return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); } #endregion diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs index 2ef039f..b28890e 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs @@ -13,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 partial class ReadOnlyMongoRepository + public abstract partial class ReadOnlyMongoRepository : KeyTypedReadOnlyMongoRepository, IReadOnlyMongoRepository { /// /// The constructor taking a connection string and a database name. @@ -249,9 +249,9 @@ namespace MongoDbGenericRepository where TKey : IEquatable { return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefaultAsync(); } /// @@ -321,8 +321,8 @@ namespace MongoDbGenericRepository where TKey : IEquatable { return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefaultAsync(); + .Project(maxValueSelector) + .FirstOrDefaultAsync(); } /// diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs deleted file mode 100644 index 7d32597..0000000 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace MongoDbGenericRepository -{ - /// - /// The ReadOnlyMongoRepository implements the readonly functionality of the IReadOnlyMongoRepository. - /// - public abstract partial class ReadOnlyMongoRepository : KeyTypedReadOnlyMongoRepository, IReadOnlyMongoRepository - { - } -}