From b77978e57a8d8ff427cf11a9eb1909f199f943ba Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Thu, 7 Feb 2019 08:47:27 +0000 Subject: [PATCH 1/7] introucting KeyTypedReadOnlyMongoRepository --- .../KeyTypedReadOnlyMongoRepository.cs | 331 +++++++++++ .../ReadOnlyMongoRepository.TKey.cs | 522 ++++++++++++++++++ 2 files changed, 853 insertions(+) create mode 100644 MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs create mode 100644 MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs diff --git a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs new file mode 100644 index 0000000..3cf82d8 --- /dev/null +++ b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs @@ -0,0 +1,331 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + /// + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. + /// + public abstract class KeyTypedReadOnlyMongoRepository where TKey : IEquatable + { + + /// + /// The connection string. + /// + public string ConnectionString { get; set; } + + /// + /// The database name. + /// + public string DatabaseName { get; set; } + + /// + /// The MongoDbContext + /// + protected IMongoDbContext MongoDbContext = null; + + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected KeyTypedReadOnlyMongoRepository(string connectionString, string databaseName) + { + MongoDbContext = new MongoDbContext(connectionString, databaseName); + } + + #region Read + + /// + /// Asynchronously returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + public async Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument + { + var filter = Builders.Filter.Eq("Id", id); + return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); + } + + /// + /// Returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + public TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument + { + var filter = Builders.Filter.Eq("Id", id); + return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + } + + /// + /// Asynchronously returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); + } + + /// + /// Returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + } + + /// + /// Returns a collection cursor. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return HandlePartitioned(partitionKey).Find(filter); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); + return (count > 0); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + var count = HandlePartitioned(partitionKey).CountDocuments(filter); + return (count > 0); + } + + /// + /// Asynchronously returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); + } + + /// + /// Returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return HandlePartitioned(partitionKey).Find(filter).ToList(); + } + + /// + /// Asynchronously counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partitionKey + public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); + } + + /// + /// Counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partitionKey + public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument + { + return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await GetByMaxAsync(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + /// + public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return GetByMax(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await GetByMinAsync(filter, minValueSelector, partitionKey); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + { + return GetByMin(filter, orderByAscending, partitionKey); + } + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await GetMaxValueAsync(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return GetMaxValue(filter, maxValueSelector, partitionKey); + } + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return GetMinValue(filter, minValueSelector, partitionKey); + } + + #endregion + + #region Utility Methods + + /// + /// Gets a collections for the type TDocument with the matching partition key (if any). + /// + /// The document type. + /// An optional partition key. + /// An + protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument + { + return MongoDbContext.GetCollection(partitionKey); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The document. + /// + protected virtual IMongoCollection HandlePartitioned(TDocument document) + where TDocument : IDocument + { + if (document is IPartitionedDocument) + { + return GetCollection(((IPartitionedDocument)document).PartitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + protected virtual IMongoCollection HandlePartitioned(string partitionKey) + where TDocument : IDocument + { + if (!string.IsNullOrEmpty(partitionKey)) + { + return GetCollection(partitionKey); + } + return GetCollection(); + } + + /// + /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object + /// + /// The document type. + /// The type of the value. + /// The expression to convert + protected static Expression> ConvertExpression(Expression> expression) + { + var param = expression.Parameters[0]; + Expression body = expression.Body; + var convert = Expression.Convert(body, typeof(object)); + return Expression.Lambda>(convert, param); + } + + #endregion + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs new file mode 100644 index 0000000..dd6e9e2 --- /dev/null +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs @@ -0,0 +1,522 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using MongoDbGenericRepository.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace MongoDbGenericRepository +{ + /// + /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. + /// Its constructor must be given a connection string and a database name. + /// + public abstract partial class ReadOnlyMongoRepository + { + /// + /// The connection string. + /// + public string ConnectionString { get; set; } + + /// + /// The database name. + /// + public string DatabaseName { get; set; } + + /// + /// The MongoDbContext + /// + protected IMongoDbContext MongoDbContext = null; + + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected ReadOnlyMongoRepository(string connectionString, string databaseName) + { + MongoDbContext = new MongoDbContext(connectionString, databaseName); + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) + { + MongoDbContext = mongoDbContext; + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected ReadOnlyMongoRepository(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 value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await GetMinValueAsync(filter, minValueSelector, partitionKey); + } + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); + } + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); + } + + #endregion + + #region Utility Methods + + /// + /// Gets a collections for the type TDocument with the matching partition key (if any). + /// + /// The document type. + /// An optional partition key. + /// An + protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument + { + return MongoDbContext.GetCollection(partitionKey); + } + + /// + /// Gets a collections for the type TDocument + /// + /// The document type. + /// The document. + /// + protected virtual IMongoCollection HandlePartitioned(TDocument document) where TDocument : IDocument + { + if (document is IPartitionedDocument) + { + return GetCollection(((IPartitionedDocument)document).PartitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The document. + /// + protected virtual IMongoCollection HandlePartitioned(TDocument document) + where TDocument : IDocument + where TKey : IEquatable + { + if (document is IPartitionedDocument) + { + return GetCollection(((IPartitionedDocument)document).PartitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The collection partition key. + /// + protected virtual IMongoCollection HandlePartitioned(string partitionKey) where TDocument : IDocument + { + if (!string.IsNullOrEmpty(partitionKey)) + { + return GetCollection(partitionKey); + } + return GetCollection(); + } + + /// + /// Gets a collections for the type TDocument with a partition key. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + protected virtual IMongoCollection GetCollection(string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return MongoDbContext.GetCollection(partitionKey); + } + + /// + /// Gets a collections for a potentially partitioned document type. + /// + /// The document type. + /// The type of the primary key. + /// The collection partition key. + /// + protected virtual IMongoCollection HandlePartitioned(string partitionKey) + where TDocument : IDocument + where TKey : IEquatable + { + if (!string.IsNullOrEmpty(partitionKey)) + { + return GetCollection(partitionKey); + } + return GetCollection(); + } + + /// + /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object + /// + /// The document type. + /// The type of the value. + /// The expression to convert + protected static Expression> ConvertExpression(Expression> expression) + { + var param = expression.Parameters[0]; + Expression body = expression.Body; + var convert = Expression.Convert(body, typeof(object)); + return Expression.Lambda>(convert, param); + } + + #endregion + } +} \ No newline at end of file From 9edd7e97feeb2f0280fc775437b85eed5af3eca3 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Thu, 7 Feb 2019 08:48:36 +0000 Subject: [PATCH 2/7] moving TKEY related methods to there own partial class in the readonly repo --- .../ReadOnlyMongoRepository.cs | 503 ------------------ 1 file changed, 503 deletions(-) diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs index 7638cdb..fd9f2d8 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs @@ -13,48 +13,7 @@ namespace MongoDbGenericRepository /// public abstract partial class ReadOnlyMongoRepository : IReadOnlyMongoRepository { - /// - /// The connection string. - /// - public string ConnectionString { get; set; } - /// - /// The database name. - /// - public string DatabaseName { get; set; } - - /// - /// The MongoDbContext - /// - protected IMongoDbContext MongoDbContext = null; - - /// - /// The constructor taking a connection string and a database name. - /// - /// The connection string of the MongoDb server. - /// The name of the database against which you want to perform operations. - protected ReadOnlyMongoRepository(string connectionString, string databaseName) - { - MongoDbContext = new MongoDbContext(connectionString, databaseName); - } - - /// - /// The contructor taking a . - /// - /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) - { - MongoDbContext = mongoDbContext; - } - - /// - /// The contructor taking a . - /// - /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) - { - MongoDbContext = new MongoDbContext(mongoDatabase); - } #region Read @@ -236,276 +195,6 @@ namespace MongoDbGenericRepository return GetByMin(filter, orderByAscending, partitionKey); } - #endregion - - #region Read TKey - - /// - /// Asynchronously returns one document given its id. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public async Task GetByIdAsync(TKey id, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", id); - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// Returns one document given its id. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public TDocument GetById(TKey id, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var filter = Builders.Filter.Eq("Id", id); - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// Asynchronously returns one document given an expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task GetOneAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// Returns one document given an expression filter. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public TDocument GetOne(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// Returns a collection cursor. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public IFindFluent GetCursor(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter); - } - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task AnyAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - return (count > 0); - } - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public bool Any(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - var count = HandlePartitioned(partitionKey).CountDocuments(filter); - return (count > 0); - } - - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task> GetAllAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); - } - - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partition key. - public List GetAll(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter).ToList(); - } - - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public async Task CountAsync(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - } - - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// The type of the primary key for a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public long Count(Expression> filter, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefault(); - } - - /// - /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); - } - - /// - /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefault(); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - private IFindFluent GetMinMongoQuery(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(ConvertExpression(minValueSelector)) - .Limit(1); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partition key. - private IFindFluent GetMaxMongoQuery(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(ConvertExpression(maxValueSelector)) - .Limit(1); - } - /// /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. /// @@ -520,23 +209,6 @@ namespace MongoDbGenericRepository return await GetMaxValueAsync(filter, maxValueSelector, partitionKey); } - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefaultAsync(); - } - /// /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. /// @@ -551,55 +223,6 @@ namespace MongoDbGenericRepository return GetMaxValue(filter, maxValueSelector, partitionKey); } - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - - return GetMaxMongoQuery(filter, maxValueSelector, partitionKey) - .Project(maxValueSelector) - .FirstOrDefault(); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetMinValueAsync(filter, minValueSelector, partitionKey); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); - } - /// /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. /// @@ -614,132 +237,6 @@ namespace MongoDbGenericRepository return GetMinValue(filter, minValueSelector, partitionKey); } - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the primary key. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); - } - #endregion - - #region Utility Methods - - /// - /// Gets a collections for the type TDocument with the matching partition key (if any). - /// - /// The document type. - /// An optional partition key. - /// An - protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument - { - return MongoDbContext.GetCollection(partitionKey); - } - - /// - /// Gets a collections for the type TDocument - /// - /// The document type. - /// The document. - /// - protected virtual IMongoCollection HandlePartitioned(TDocument document) where TDocument : IDocument - { - if (document is IPartitionedDocument) - { - return GetCollection(((IPartitionedDocument)document).PartitionKey); - } - return GetCollection(); - } - - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The type of the primary key. - /// The document. - /// - protected virtual IMongoCollection HandlePartitioned(TDocument document) - where TDocument : IDocument - where TKey : IEquatable - { - if (document is IPartitionedDocument) - { - return GetCollection(((IPartitionedDocument)document).PartitionKey); - } - return GetCollection(); - } - - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The collection partition key. - /// - protected virtual IMongoCollection HandlePartitioned(string partitionKey) where TDocument : IDocument - { - if (!string.IsNullOrEmpty(partitionKey)) - { - return GetCollection(partitionKey); - } - return GetCollection(); - } - - /// - /// Gets a collections for the type TDocument with a partition key. - /// - /// The document type. - /// The type of the primary key. - /// The collection partition key. - /// - protected virtual IMongoCollection GetCollection(string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return MongoDbContext.GetCollection(partitionKey); - } - - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The type of the primary key. - /// The collection partition key. - /// - protected virtual IMongoCollection HandlePartitioned(string partitionKey) - where TDocument : IDocument - where TKey : IEquatable - { - if (!string.IsNullOrEmpty(partitionKey)) - { - return GetCollection(partitionKey); - } - return GetCollection(); - } - - /// - /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object - /// - /// The document type. - /// The type of the value. - /// The expression to convert - protected static Expression> ConvertExpression(Expression> expression) - { - var param = expression.Parameters[0]; - Expression body = expression.Body; - var convert = Expression.Convert(body, typeof(object)); - return Expression.Lambda>(convert, param); - } - - #endregion - } } From f773e599d02578f3fcfb5db226d473bb806de759 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Thu, 4 Apr 2019 22:48:09 +0100 Subject: [PATCH 3/7] some good progress on refactoring into the KeyTyped repo for read only functionality --- .../IKeyTypedReadOnlyMongoRepository.cs | 203 +++++++++++++++ .../Abstractions/IReadOnlyMongoRepository.cs | 189 +------------- .../KeyTypedReadOnlyMongoRepository.cs | 101 +++++++- MongoDbGenericRepository/MongoDbContext.cs | 6 +- .../ReadOnlyMongoRepository.TKey.cs | 93 +------ .../ReadOnlyMongoRepository.cs | 235 +----------------- 6 files changed, 303 insertions(+), 524 deletions(-) create mode 100644 MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs diff --git a/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs new file mode 100644 index 0000000..857ee97 --- /dev/null +++ b/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDbGenericRepository.Models; + +namespace MongoDbGenericRepository +{ + public interface IKeyTypedReadOnlyMongoRepository where TKey : IEquatable + { + /// + /// The connection string. + /// + string ConnectionString { get; set; } + /// + /// The database name. + /// + string DatabaseName { get; set; } + + #region Read + + /// + /// Asynchronously returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns one document given its id. + /// + /// The type representing a Document. + /// The Id of the document you want to get. + /// An optional partition key. + TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns one document given an expression filter. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns a collection cursor. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Returns a list of the documents matching the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Asynchronously counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + /// + /// Counts how many documents match the filter condition. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// An optional partition key. + long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument; + + #endregion + + #region Min / Max + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + /// + TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument; + + #endregion + + } +} \ No newline at end of file diff --git a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs index a79d3e9..bfce1ec 100644 --- a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs @@ -10,108 +10,8 @@ namespace MongoDbGenericRepository /// /// The IReadOnlyMongoRepository exposes the readonly functionality of the BaseMongoRepository. /// - public interface IReadOnlyMongoRepository + public interface IReadOnlyMongoRepository : IKeyTypedReadOnlyMongoRepository { - /// - /// The connection string. - /// - string ConnectionString { get; set; } - /// - /// The database name. - /// - string DatabaseName { get; set; } - - #region Read - - /// - /// Asynchronously returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - Task GetByIdAsync(Guid id, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - TDocument GetById(Guid id, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns a collection cursor. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument; - - #endregion #region Read TKey @@ -241,47 +141,6 @@ namespace MongoDbGenericRepository #region Min / Max - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - /// - TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument; - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument; - /// /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. /// @@ -330,17 +189,6 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument; - /// /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. /// @@ -353,17 +201,6 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument; - /// /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. /// @@ -376,17 +213,6 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument; - /// /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. /// @@ -400,17 +226,6 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument; - /// /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. /// @@ -435,7 +250,7 @@ namespace MongoDbGenericRepository /// A LINQ expression filter. /// The field you want to sum. /// The partition key of your document, if any. - Task SumByAsync(Expression> filter, + Task SumByAsync(Expression> filter, Expression> selector, string partitionKey = null) where TDocument : IDocument; diff --git a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs index 3cf82d8..2f071df 100644 --- a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs @@ -9,13 +9,14 @@ using System.Threading.Tasks; namespace MongoDbGenericRepository { + + /// /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. /// Its constructor must be given a connection string and a database name. /// - public abstract class KeyTypedReadOnlyMongoRepository where TKey : IEquatable + public abstract class KeyTypedReadOnlyMongoRepository : IKeyTypedReadOnlyMongoRepository where TKey : IEquatable { - /// /// The connection string. /// @@ -41,6 +42,24 @@ namespace MongoDbGenericRepository MongoDbContext = new MongoDbContext(connectionString, databaseName); } + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedReadOnlyMongoRepository(IMongoDbContext mongoDbContext) + { + MongoDbContext = mongoDbContext; + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected KeyTypedReadOnlyMongoRepository(IMongoDatabase mongoDatabase) + { + MongoDbContext = new MongoDbContext(mongoDatabase); + } + #region Read /// @@ -178,7 +197,10 @@ namespace MongoDbGenericRepository public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetByMaxAsync(filter, maxValueSelector, partitionKey); + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(maxValueSelector) + .Limit(1) + .FirstOrDefaultAsync(); } /// @@ -192,7 +214,10 @@ namespace MongoDbGenericRepository public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetByMax(filter, maxValueSelector, partitionKey); + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(maxValueSelector) + .Limit(1) + .FirstOrDefault(); } /// @@ -205,7 +230,10 @@ namespace MongoDbGenericRepository public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetByMinAsync(filter, minValueSelector, partitionKey); + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefaultAsync(); } /// @@ -213,12 +241,15 @@ namespace MongoDbGenericRepository /// /// The document type. /// A LINQ expression filter. - /// A property selector to order by ascending. + /// A property selector to order by ascending. /// An optional partitionKey. - public TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + public TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetByMin(filter, orderByAscending, partitionKey); + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(minValueSelector) + .Limit(1) + .FirstOrDefault(); } /// @@ -232,7 +263,7 @@ namespace MongoDbGenericRepository public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetMaxValueAsync(filter, maxValueSelector, partitionKey); + return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey).Project(maxValueSelector).FirstOrDefaultAsync(); } /// @@ -246,7 +277,21 @@ namespace MongoDbGenericRepository public TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetMaxValue(filter, maxValueSelector, partitionKey); + return GetMaxMongoQuery(filter, maxValueSelector, partitionKey).Project(maxValueSelector).FirstOrDefault(); + } + + /// + /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the value used to order the query. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partition key. + public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) + where TDocument : IDocument + { + return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); } /// @@ -260,7 +305,7 @@ namespace MongoDbGenericRepository public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetMinValue(filter, minValueSelector, partitionKey); + return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); } #endregion @@ -326,6 +371,40 @@ namespace MongoDbGenericRepository return Expression.Lambda>(convert, param); } + /// + /// 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 + { + 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 + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(ConvertExpression(maxValueSelector)) + .Limit(1); + } + #endregion } } \ No newline at end of file diff --git a/MongoDbGenericRepository/MongoDbContext.cs b/MongoDbGenericRepository/MongoDbContext.cs index 175c4c4..c5921b9 100644 --- a/MongoDbGenericRepository/MongoDbContext.cs +++ b/MongoDbGenericRepository/MongoDbContext.cs @@ -63,8 +63,8 @@ namespace MongoDbGenericRepository Client = new MongoClient(connectionString); Database = Client.GetDatabase(databaseName); } - - /// + + /// /// The constructor of the MongoDbContext, it needs a connection string and a database name. /// /// The MongoClient. @@ -111,7 +111,7 @@ namespace MongoDbGenericRepository /// Given the document type and the partition key, returns the name of the collection it belongs to. /// /// The type representing a Document. - /// The value of the partition key. + /// The value of the partition key. /// The name of the collection. private string GetCollectionName(string partitionKey) { diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs index dd6e9e2..2ef039f 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs @@ -15,47 +15,29 @@ namespace MongoDbGenericRepository /// public abstract partial class ReadOnlyMongoRepository { - /// - /// The connection string. - /// - public string ConnectionString { get; set; } - - /// - /// The database name. - /// - public string DatabaseName { get; set; } - - /// - /// The MongoDbContext - /// - protected IMongoDbContext MongoDbContext = null; - /// /// The constructor taking a connection string and a database name. /// /// The connection string of the MongoDb server. /// The name of the database against which you want to perform operations. - protected ReadOnlyMongoRepository(string connectionString, string databaseName) + protected ReadOnlyMongoRepository(string connectionString, string databaseName) : base(connectionString, databaseName) { - MongoDbContext = new MongoDbContext(connectionString, databaseName); } /// /// The contructor taking a . /// /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) + protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) { - MongoDbContext = mongoDbContext; } /// /// The contructor taking a . /// /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) + protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) { - MongoDbContext = new MongoDbContext(mongoDatabase); } #region Read TKey @@ -362,20 +344,6 @@ namespace MongoDbGenericRepository .FirstOrDefault(); } - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetMinValueAsync(filter, minValueSelector, partitionKey); - } - /// /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. /// @@ -412,32 +380,6 @@ namespace MongoDbGenericRepository #region Utility Methods - /// - /// Gets a collections for the type TDocument with the matching partition key (if any). - /// - /// The document type. - /// An optional partition key. - /// An - protected virtual IMongoCollection GetCollection(string partitionKey = null) where TDocument : IDocument - { - return MongoDbContext.GetCollection(partitionKey); - } - - /// - /// Gets a collections for the type TDocument - /// - /// The document type. - /// The document. - /// - protected virtual IMongoCollection HandlePartitioned(TDocument document) where TDocument : IDocument - { - if (document is IPartitionedDocument) - { - return GetCollection(((IPartitionedDocument)document).PartitionKey); - } - return GetCollection(); - } - /// /// Gets a collections for a potentially partitioned document type. /// @@ -456,21 +398,6 @@ namespace MongoDbGenericRepository return GetCollection(); } - /// - /// Gets a collections for a potentially partitioned document type. - /// - /// The document type. - /// The collection partition key. - /// - protected virtual IMongoCollection HandlePartitioned(string partitionKey) where TDocument : IDocument - { - if (!string.IsNullOrEmpty(partitionKey)) - { - return GetCollection(partitionKey); - } - return GetCollection(); - } - /// /// Gets a collections for the type TDocument with a partition key. /// @@ -503,20 +430,6 @@ namespace MongoDbGenericRepository return GetCollection(); } - /// - /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object - /// - /// The document type. - /// The type of the value. - /// The expression to convert - protected static Expression> ConvertExpression(Expression> expression) - { - var param = expression.Parameters[0]; - Expression body = expression.Body; - var convert = Expression.Convert(body, typeof(object)); - return Expression.Lambda>(convert, param); - } - #endregion } } \ No newline at end of file diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs index fd9f2d8..7d32597 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs @@ -1,242 +1,11 @@ -using MongoDB.Driver; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Linq.Expressions; -using MongoDbGenericRepository.Models; -using System.Linq; +using System; namespace MongoDbGenericRepository { /// /// The ReadOnlyMongoRepository implements the readonly functionality of the IReadOnlyMongoRepository. /// - public abstract partial class ReadOnlyMongoRepository : IReadOnlyMongoRepository + public abstract partial class ReadOnlyMongoRepository : KeyTypedReadOnlyMongoRepository, IReadOnlyMongoRepository { - - - #region Read - - /// - /// Asynchronously returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public async Task GetByIdAsync(Guid id, string partitionKey = null) where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", id); - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// Returns one document given its id. - /// - /// The type representing a Document. - /// The Id of the document you want to get. - /// An optional partition key. - public TDocument GetById(Guid id, string partitionKey = null) where TDocument : IDocument - { - var filter = Builders.Filter.Eq("Id", id); - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// Asynchronously returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); - } - - /// - /// Returns one document given an expression filter. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); - } - - /// - /// Returns a collection cursor. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter); - } - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - return (count > 0); - } - - /// - /// Returns true if any of the document of the collection matches the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - var count = HandlePartitioned(partitionKey).CountDocuments(filter); - return (count > 0); - } - - /// - /// Asynchronously returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); - } - - /// - /// Returns a list of the documents matching the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partition key. - public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter).ToList(); - } - - /// - /// Asynchronously counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - } - - /// - /// Counts how many documents match the filter condition. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// An optional partitionKey - public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument - { - return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetByMaxAsync(filter, maxValueSelector, partitionKey); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by descending. - /// An optional partitionKey. - /// - public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return GetByMax(filter, maxValueSelector, partitionKey); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetByMinAsync(filter, minValueSelector, partitionKey); - } - - /// - /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. - /// - /// The document type. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) - where TDocument : IDocument - { - return GetByMin(filter, orderByAscending, partitionKey); - } - - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return await GetMaxValueAsync(filter, maxValueSelector, partitionKey); - } - - /// - /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partitionKey. - public TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return GetMaxValue(filter, maxValueSelector, partitionKey); - } - - /// - /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. - /// - /// The document type. - /// The type of the value used to order the query. - /// A LINQ expression filter. - /// A property selector to order by ascending. - /// An optional partition key. - public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) - where TDocument : IDocument - { - return GetMinValue(filter, minValueSelector, partitionKey); - } - - #endregion } } From ba723be738c3ae5a12e6b4fb5512d7c000dac888 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Thu, 4 Apr 2019 23:45:07 +0100 Subject: [PATCH 4/7] 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 - { - } -} From 75b894cb2a949e370791c75a6255fc690ab0e386 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Wed, 10 Apr 2019 22:07:15 +0100 Subject: [PATCH 5/7] ran tests + removed obsolete methods --- .../Infrastructure/MongoDbDocumentTestBase.cs | 2 +- .../MongoDbTKeyDocumentTestBase.cs | 2 +- IntegrationTests/App.config | 2 +- .../Infrastructure/MongoDBDocumentTestBase.cs | 2 +- .../MongoDbTKeyDocumentTestBase.cs | 2 +- IntegrationTests/IntegrationTests.csproj | 35 +++++++++++-------- IntegrationTests/packages.config | 13 ++++--- 7 files changed, 31 insertions(+), 27 deletions(-) diff --git a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs index c70056c..0c333a9 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs @@ -235,7 +235,7 @@ namespace CoreIntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.True(1 == count, GetTestName()); } diff --git a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index 9d99665..e4f2051 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -236,7 +236,7 @@ namespace CoreIntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.True (1 == count, GetTestName()); } diff --git a/IntegrationTests/App.config b/IntegrationTests/App.config index fb9836a..beb386a 100644 --- a/IntegrationTests/App.config +++ b/IntegrationTests/App.config @@ -11,7 +11,7 @@ - + diff --git a/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs b/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs index ebd66e2..ea3dfd6 100644 --- a/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs +++ b/IntegrationTests/Infrastructure/MongoDBDocumentTestBase.cs @@ -202,7 +202,7 @@ namespace IntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.AreEqual(1, count, GetTestName()); } diff --git a/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index 3d0cf8c..e6b87d9 100644 --- a/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/IntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -204,7 +204,7 @@ namespace IntegrationTests.Infrastructure SUT.AddOne(document); // Act var cursor = SUT.GetCursor(x => x.Id.Equals(document.Id), PartitionKey); - var count = cursor.Count(); + var count = cursor.CountDocuments(); // Assert Assert.AreEqual(1, count, GetTestName()); } diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj index c5b56bc..9a6c6b3 100644 --- a/IntegrationTests/IntegrationTests.csproj +++ b/IntegrationTests/IntegrationTests.csproj @@ -30,33 +30,32 @@ 4 - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\DnsClient.dll + + ..\packages\DnsClient.1.2.0\lib\net45\DnsClient.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDB.Bson.dll + + ..\packages\MongoDB.Bson.2.8.0\lib\net452\MongoDB.Bson.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDB.Driver.dll + + ..\packages\MongoDB.Driver.2.8.0\lib\net452\MongoDB.Driver.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDB.Driver.Core.dll - - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\MongoDbGenericRepository.dll + + ..\packages\MongoDB.Driver.Core.2.8.0\lib\net452\MongoDB.Driver.Core.dll ..\packages\NUnit.3.9.0\lib\net45\nunit.framework.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\System.Buffers.dll + + ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll - - ..\packages\MongoDbGenericRepository.1.3.8\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + + ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll + True + True @@ -86,5 +85,11 @@ + + + {efc776c4-2af3-440c-be80-3fbe335817a5} + MongoDbGenericRepository + + \ No newline at end of file diff --git a/IntegrationTests/packages.config b/IntegrationTests/packages.config index 94c72ae..1d92b40 100644 --- a/IntegrationTests/packages.config +++ b/IntegrationTests/packages.config @@ -1,12 +1,11 @@  - - - - - + + + + - - + + \ No newline at end of file From d2f465b0631267924268adb0464b10a040b1f0b3 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Wed, 10 Apr 2019 23:48:44 +0100 Subject: [PATCH 6/7] reorg + inheritance setup, using interface segregation to split concern / exposure of methods. --- .../IKeyTypedReadOnlyMongoRepository.cs | 63 ++- .../Abstractions/IReadOnlyMongoRepository.cs | 266 +---------- .../BaseMongoDbRepository.cs | 5 +- ...goRepository.TKey.cs => BaseRepository.cs} | 426 +++++++++++++++++- .../KeyTypedBaseMongoDbRepository.cs | 5 +- .../KeyTypedReadOnlyMongoRepository.cs | 194 ++++---- .../MongoDbGenericRepository.csproj | 4 +- .../ReadOnlyMongoRepository.Maths.cs | 52 --- .../ReadOnlyMongoRepository.cs | 37 ++ 9 files changed, 600 insertions(+), 452 deletions(-) rename MongoDbGenericRepository/{ReadOnlyMongoRepository.TKey.cs => BaseRepository.cs} (50%) delete mode 100644 MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs create mode 100644 MongoDbGenericRepository/ReadOnlyMongoRepository.cs diff --git a/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs index 857ee97..a2b42c1 100644 --- a/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IKeyTypedReadOnlyMongoRepository.cs @@ -7,17 +7,9 @@ using MongoDbGenericRepository.Models; namespace MongoDbGenericRepository { - public interface IKeyTypedReadOnlyMongoRepository where TKey : IEquatable + public interface IKeyTypedReadOnlyMongoRepository : IBaseReadOnlyRepository + where TKey : IEquatable { - /// - /// The connection string. - /// - string ConnectionString { get; set; } - /// - /// The database name. - /// - string DatabaseName { get; set; } - #region Read /// @@ -199,5 +191,56 @@ namespace MongoDbGenericRepository #endregion + #region Maths + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + int SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + decimal SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument; + + #endregion Maths } } \ No newline at end of file diff --git a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs index bfce1ec..a5e295e 100644 --- a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs @@ -1,273 +1,11 @@ -using MongoDB.Driver; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Linq.Expressions; -using MongoDbGenericRepository.Models; +using System; namespace MongoDbGenericRepository { /// /// The IReadOnlyMongoRepository exposes the readonly functionality of the BaseMongoRepository. /// - public interface IReadOnlyMongoRepository : IKeyTypedReadOnlyMongoRepository + public interface IReadOnlyMongoRepository : IBaseReadOnlyRepository, IKeyTypedReadOnlyMongoRepository { - - #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; - - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable; - #endregion Sum } - } diff --git a/MongoDbGenericRepository/BaseMongoDbRepository.cs b/MongoDbGenericRepository/BaseMongoDbRepository.cs index f8c9c75..db9dd3d 100644 --- a/MongoDbGenericRepository/BaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/BaseMongoDbRepository.cs @@ -20,9 +20,8 @@ namespace MongoDbGenericRepository /// /// The connection string of the MongoDb server. /// The name of the database against which you want to perform operations. - protected BaseMongoRepository(string connectionString, string databaseName) : base(connectionString, databaseName) + protected BaseMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) { - MongoDbContext = new MongoDbContext(connectionString, databaseName); } /// @@ -31,7 +30,6 @@ namespace MongoDbGenericRepository /// A mongodb context implementing protected BaseMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) { - MongoDbContext = mongoDbContext; } /// @@ -40,7 +38,6 @@ namespace MongoDbGenericRepository /// A mongodb context implementing protected BaseMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) { - MongoDbContext = new MongoDbContext(mongoDatabase); } #region Create diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs b/MongoDbGenericRepository/BaseRepository.cs similarity index 50% rename from MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs rename to MongoDbGenericRepository/BaseRepository.cs index b28890e..823c1f8 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.TKey.cs +++ b/MongoDbGenericRepository/BaseRepository.cs @@ -9,37 +9,356 @@ using System.Threading.Tasks; namespace MongoDbGenericRepository { - /// - /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. - /// Its constructor must be given a connection string and a database name. - /// - public abstract partial class ReadOnlyMongoRepository : KeyTypedReadOnlyMongoRepository, IReadOnlyMongoRepository + 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 ReadOnlyMongoRepository(string connectionString, string databaseName) : base(connectionString, databaseName) + 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 ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + protected BaseReadOnlyRepository(IMongoDbContext mongoDbContext) { + MongoDbContext = mongoDbContext; } /// /// The contructor taking a . /// /// A mongodb context implementing - protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + protected BaseReadOnlyRepository(IMongoDatabase mongoDatabase) { + MongoDbContext = new MongoDbContext(mongoDatabase); } + #region Read TKey /// @@ -378,8 +697,83 @@ namespace MongoDbGenericRepository #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. /// @@ -430,6 +824,20 @@ namespace MongoDbGenericRepository return GetCollection(); } + /// + /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object + /// + /// The document type. + /// The type of the value. + /// The expression to convert + protected static Expression> ConvertExpression(Expression> expression) + { + var param = expression.Parameters[0]; + Expression body = expression.Body; + var convert = Expression.Convert(body, typeof(object)); + return Expression.Lambda>(convert, param); + } + #endregion } -} \ No newline at end of file +} diff --git a/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs b/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs index 0adba7f..88d6f25 100644 --- a/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs +++ b/MongoDbGenericRepository/KeyTypedBaseMongoDbRepository.cs @@ -20,7 +20,7 @@ namespace MongoDbGenericRepository /// /// 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) + protected KeyTypedBaseMongoDbRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) { } @@ -40,7 +40,6 @@ namespace MongoDbGenericRepository { } - #region Create /// @@ -129,7 +128,6 @@ namespace MongoDbGenericRepository #endregion Create - /// /// Sets the value of the document Id if it is not set already. /// @@ -149,6 +147,5 @@ namespace MongoDbGenericRepository document.Id = IdGenerator.GetId(); } } - } } diff --git a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs index 7c41e7e..3f3d37f 100644 --- a/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/KeyTypedReadOnlyMongoRepository.cs @@ -9,55 +9,35 @@ using System.Threading.Tasks; namespace MongoDbGenericRepository { - - /// /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. /// Its constructor must be given a connection string and a database name. /// - public abstract class KeyTypedReadOnlyMongoRepository : IKeyTypedReadOnlyMongoRepository where TKey : IEquatable + public abstract class KeyTypedReadOnlyMongoRepository : BaseReadOnlyRepository, IKeyTypedReadOnlyMongoRepository where TKey : IEquatable { - /// - /// The connection string. - /// - public string ConnectionString { get; set; } - - /// - /// The database name. - /// - public string DatabaseName { get; set; } - - /// - /// The MongoDbContext - /// - protected IMongoDbContext MongoDbContext = null; - /// /// The constructor taking a connection string and a database name. /// /// The connection string of the MongoDb server. /// The name of the database against which you want to perform operations. - protected KeyTypedReadOnlyMongoRepository(string connectionString, string databaseName) + protected KeyTypedReadOnlyMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) { - MongoDbContext = new MongoDbContext(connectionString, databaseName); } /// /// The contructor taking a . /// /// A mongodb context implementing - protected KeyTypedReadOnlyMongoRepository(IMongoDbContext mongoDbContext) + protected KeyTypedReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) { - MongoDbContext = mongoDbContext; } /// /// The contructor taking a . /// /// A mongodb context implementing - protected KeyTypedReadOnlyMongoRepository(IMongoDatabase mongoDatabase) + protected KeyTypedReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) { - MongoDbContext = new MongoDbContext(mongoDatabase); } #region Read @@ -70,8 +50,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument { - var filter = Builders.Filter.Eq("Id", id); - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); + return await base.GetByIdAsync(id, partitionKey); } /// @@ -82,8 +61,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument { - var filter = Builders.Filter.Eq("Id", id); - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + return base.GetById(id, partitionKey); } /// @@ -94,7 +72,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); + return await base.GetOneAsync(filter, partitionKey); } /// @@ -105,7 +83,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); + return base.GetOne(filter, partitionKey); } /// @@ -116,7 +94,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return HandlePartitioned(partitionKey).Find(filter); + return base.GetCursor(filter, partitionKey); } /// @@ -127,8 +105,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); - return (count > 0); + return await base.AnyAsync(filter, partitionKey); } /// @@ -139,8 +116,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument { - var count = HandlePartitioned(partitionKey).CountDocuments(filter); - return (count > 0); + return base.Any(filter, partitionKey); } /// @@ -151,7 +127,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); + return await base.GetAllAsync(filter, partitionKey); } /// @@ -162,7 +138,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return HandlePartitioned(partitionKey).Find(filter).ToList(); + return base.GetAll(filter, partitionKey); } /// @@ -173,7 +149,7 @@ namespace MongoDbGenericRepository /// An optional partitionKey public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); + return await base.CountAsync(filter, partitionKey); } /// @@ -184,7 +160,7 @@ namespace MongoDbGenericRepository /// An optional partitionKey public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + return base.Count(filter, partitionKey); } /// @@ -197,10 +173,7 @@ namespace MongoDbGenericRepository public async Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); + return await base.GetByMaxAsync(filter, maxValueSelector, partitionKey); } /// @@ -214,10 +187,7 @@ namespace MongoDbGenericRepository public TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(maxValueSelector) - .Limit(1) - .FirstOrDefault(); + return base.GetByMax(filter, maxValueSelector, partitionKey); } /// @@ -230,10 +200,7 @@ namespace MongoDbGenericRepository public async Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefaultAsync(); + return await base.GetByMinAsync(filter, minValueSelector, partitionKey); } /// @@ -246,10 +213,7 @@ namespace MongoDbGenericRepository public TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortBy(minValueSelector) - .Limit(1) - .FirstOrDefault(); + return base.GetByMin(filter, minValueSelector, partitionKey); } /// @@ -263,7 +227,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 base.GetMaxValueAsync(filter, maxValueSelector, partitionKey); } /// @@ -277,7 +241,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 base.GetMaxValue(filter, maxValueSelector, partitionKey); } /// @@ -291,7 +255,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 base.GetMinValueAsync(filter, minValueSelector, partitionKey); } /// @@ -305,11 +269,75 @@ 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 base.GetMinValue(filter, minValueSelector, partitionKey); } #endregion + #region Maths + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + { + return await base.SumByAsync(filter, selector, partitionKey); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual async Task SumByAsync(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + { + return await base.SumByAsync(filter, selector, partitionKey); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual int SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + { + return base.SumBy(filter, selector, partitionKey); + } + + /// + /// Sums the values of a selected field for a given filtered collection of documents. + /// + /// The type representing a Document. + /// A LINQ expression filter. + /// The field you want to sum. + /// The partition key of your document, if any. + public virtual decimal SumBy(Expression> filter, + Expression> selector, + string partitionKey = null) + where TDocument : IDocument + { + return base.SumBy(filter, selector, partitionKey); + } + + #endregion Maths + #region Utility Methods /// @@ -357,54 +385,6 @@ namespace MongoDbGenericRepository 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); - } - - /// - /// 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 - { - 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 - { - return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) - .SortByDescending(ConvertExpression(maxValueSelector)) - .Limit(1); - } - #endregion } } \ No newline at end of file diff --git a/MongoDbGenericRepository/MongoDbGenericRepository.csproj b/MongoDbGenericRepository/MongoDbGenericRepository.csproj index bed1e2f..55a2c7d 100644 --- a/MongoDbGenericRepository/MongoDbGenericRepository.csproj +++ b/MongoDbGenericRepository/MongoDbGenericRepository.csproj @@ -1,7 +1,7 @@ - + - net45;netstandard1.5;netstandard2.0 + net45;netstandard2.0;netstandard1.5; MongoDbGenericRepository 1.2.0 Alexandre Spieser diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs deleted file mode 100644 index b75fe11..0000000 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.Maths.cs +++ /dev/null @@ -1,52 +0,0 @@ -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using MongoDbGenericRepository.Models; -using System; -using System.Linq; -using System.Linq.Expressions; -using System.Threading.Tasks; - -namespace MongoDbGenericRepository -{ - /// - /// The base Repository, it is meant to be inherited from by your custom custom MongoRepository implementation. - /// Its constructor must be given a connection string and a database name. - /// - public abstract partial class ReadOnlyMongoRepository - { - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - public virtual async Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument - { - return await SumByAsync(filter, selector, partitionKey); - } - - /// - /// Sums the values of a selected field for a given filtered collection of documents. - /// - /// The type representing a Document. - /// A LINQ expression filter. - /// The field you want to sum. - /// The partition key of your document, if any. - public virtual async Task SumByAsync(Expression> filter, - Expression> selector, - string partitionKey = null) - where TDocument : IDocument - where TKey : IEquatable - { - return await GetCollection(partitionKey) - .AsQueryable() - .Where(filter) - .SumAsync(selector); - } - - } -} \ No newline at end of file diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs new file mode 100644 index 0000000..fe995a9 --- /dev/null +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs @@ -0,0 +1,37 @@ +using MongoDB.Driver; +using System; + +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 + { + /// + /// The constructor taking a connection string and a database name. + /// + /// The connection string of the MongoDb server. + /// The name of the database against which you want to perform operations. + protected ReadOnlyMongoRepository(string connectionString, string databaseName = null) : base(connectionString, databaseName) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected ReadOnlyMongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext) + { + } + + /// + /// The contructor taking a . + /// + /// A mongodb context implementing + protected ReadOnlyMongoRepository(IMongoDatabase mongoDatabase) : base(mongoDatabase) + { + } + } +} \ No newline at end of file From 2f29efafe3872d67a688f4c82998ec0d4b806806 Mon Sep 17 00:00:00 2001 From: Alexandre SPIESER Date: Wed, 10 Apr 2019 23:57:52 +0100 Subject: [PATCH 7/7] SumByDecimal() test --- .../Infrastructure/MongoDbDocumentTestBase.cs | 25 ++++++++++++++++++- .../MongoDbTKeyDocumentTestBase.cs | 25 ++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs index 0c333a9..a1f3944 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs @@ -1078,7 +1078,7 @@ namespace CoreIntegrationTests.Infrastructure #region Math [Fact] - public async Task SumByAsync() + public async Task SumByDecimalAsync() { // Arrange var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; @@ -1100,6 +1100,29 @@ namespace CoreIntegrationTests.Infrastructure Assert.Equal(expectedSum, result); } + [Fact] + public void SumByDecimal() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => + { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.Nested.SomeAmount = 5m; + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedSum = documents.Sum(e => e.Nested.SomeAmount); + + // Act + var result = SUT.SumBy(e => e.SomeContent == criteria, e => e.Nested.SomeAmount, PartitionKey); + + // Assert + Assert.Equal(expectedSum, result); + } + #endregion Math #region Test Utils diff --git a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index e4f2051..e4b0843 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -1071,7 +1071,7 @@ namespace CoreIntegrationTests.Infrastructure #region Math [Fact] - public async Task SumByAsync() + public async Task SumByDecimalAsync() { // Arrange var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; @@ -1093,6 +1093,29 @@ namespace CoreIntegrationTests.Infrastructure Assert.Equal(expectedSum, result); } + [Fact] + public void SumByDecimal() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => + { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.Nested.SomeAmount = 5m; + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedSum = documents.Sum(e => e.Nested.SomeAmount); + + // Act + var result = SUT.SumBy(e => e.SomeContent == criteria, e => e.Nested.SomeAmount, PartitionKey); + + // Assert + Assert.Equal(expectedSum, result); + } + #endregion Math #region Test Utils