From c24fa78907436fd4c222fc795e91ede4c00f6978 Mon Sep 17 00:00:00 2001 From: alexandre-spieser Date: Sun, 27 Aug 2017 15:37:06 +0000 Subject: [PATCH] Added interface --- IntegrationTests/ITestsRepository.cs | 9 + IntegrationTests/InsertTests.cs | 63 ++- IntegrationTests/IntegrationTests.csproj | 2 + IntegrationTests/UpdateTests.cs | 12 + MongoDbGenericRepository/MongoDbRepository.cs | 404 ++++++++++++------ 5 files changed, 339 insertions(+), 151 deletions(-) create mode 100644 IntegrationTests/ITestsRepository.cs create mode 100644 IntegrationTests/UpdateTests.cs diff --git a/IntegrationTests/ITestsRepository.cs b/IntegrationTests/ITestsRepository.cs new file mode 100644 index 0000000..fa80ddb --- /dev/null +++ b/IntegrationTests/ITestsRepository.cs @@ -0,0 +1,9 @@ +using MongoDbGenericRepository; + +namespace IntegrationTests +{ + public interface ITestsRepository : IBaseMongoRepository + { + void DropTestCollection(); + } +} \ No newline at end of file diff --git a/IntegrationTests/InsertTests.cs b/IntegrationTests/InsertTests.cs index 5d05b1a..6bc2bf0 100644 --- a/IntegrationTests/InsertTests.cs +++ b/IntegrationTests/InsertTests.cs @@ -7,54 +7,31 @@ using System.Configuration; namespace IntegrationTests { - public class InsertTestsRepository : BaseMongoRepository + public class TestsRepository : BaseMongoRepository, ITestsRepository { /// - public InsertTestsRepository(string connectionString, string databaseName) : base(connectionString, databaseName) + public TestsRepository(string connectionString, string databaseName) : base(connectionString, databaseName) { } public void DropTestCollection() { - _mongoDbContext + _mongoDbContext.DropCollection(); } } public class InsertTests { - - private class InsertTestsDocument : Document - { - public InsertTestsDocument() - { - Version = 2; - } - public string SomeContent { get; set; } - } - - - private void Cleanup(InsertTestsDocument document) - { - SUT.DeleteOne(document); - Assert.AreEqual(0, SUT.Count(e => e.Id == document.Id)); - } - - private void Cleanup(List documents) - { - SUT.DeleteMany(documents); - SUT.Count(e => e.Id == documents[0].Id || e.Id == documents[1].Id); - } - /// /// SUT: System Under Test /// - private static InsertTestsRepository SUT { get; set; } + private static ITestsRepository SUT { get; set; } [OneTimeSetUp] public void Init() { var connectionString = ConfigurationManager.ConnectionStrings["MongoDbTests"].ConnectionString; - SUT = new InsertTestsRepository(connectionString, "MongoDbTests"); + SUT = new TestsRepository(connectionString, "MongoDbTests"); } [Test] @@ -67,8 +44,18 @@ namespace IntegrationTests // Assert long count = SUT.Count(e => e.Id == document.Id); Assert.AreEqual(1, count); - // Cleanup - Cleanup(document); + } + + [Test] + public void InsertOneAsync() + { + // Arrange + var document = new InsertTestsDocument(); + // Act + SUT.AddOne(document); + // Assert + long count = SUT.Count(e => e.Id == document.Id); + Assert.AreEqual(1, count); } [Test] @@ -81,8 +68,20 @@ namespace IntegrationTests // Assert long count = SUT.Count(e => e.Id == documents[0].Id || e.Id == documents[1].Id); Assert.AreEqual(2, count); - // Cleanup - Cleanup(documents); } + + + #region Utils + + private class InsertTestsDocument : Document + { + public InsertTestsDocument() + { + Version = 2; + } + public string SomeContent { get; set; } + } + + #endregion } } diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj index 871ebda..b924b2b 100644 --- a/IntegrationTests/IntegrationTests.csproj +++ b/IntegrationTests/IntegrationTests.csproj @@ -56,8 +56,10 @@ + + diff --git a/IntegrationTests/UpdateTests.cs b/IntegrationTests/UpdateTests.cs new file mode 100644 index 0000000..d015760 --- /dev/null +++ b/IntegrationTests/UpdateTests.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IntegrationTests +{ + class UpdateTests + { + } +} diff --git a/MongoDbGenericRepository/MongoDbRepository.cs b/MongoDbGenericRepository/MongoDbRepository.cs index 90f1f76..5ba3108 100644 --- a/MongoDbGenericRepository/MongoDbRepository.cs +++ b/MongoDbGenericRepository/MongoDbRepository.cs @@ -2,13 +2,125 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using MongoDB.Bson; using System.Linq.Expressions; using MongoDbGenericRepository.Models; +using System.Linq; namespace MongoDbGenericRepository { - public abstract class BaseMongoRepository + public interface IBaseMongoRepository + { + #region Read + + /// + /// Asynchronously returns one document given its id. + /// + /// + /// The Id of the document you want to get. + Task GetById(Guid id) where TDocument : IDocument; + + /// + /// Asynchronously returns one document given an expression filter. + /// + /// + /// A LINQ expression filter. + Task GetOneAsync(Expression> filter) where TDocument : IDocument; + + /// + /// Returns one document given an expression filter. + /// + /// + /// A LINQ expression filter. + TDocument GetOne(Expression> filter) where TDocument : IDocument; + + /// + /// Returns a collection cursor. + /// + /// + /// A LINQ expression filter. + IFindFluent GetCursor(Expression> filter) where TDocument : IDocument; + + /// + /// Asynchronously returns true if any of the document of the collection matches the filter condition. + /// + /// + /// A LINQ expression filter. + Task AnyAsync(Expression> filter) where TDocument : IDocument; + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// + /// A LINQ expression filter. + bool Any(Expression> filter) where TDocument : IDocument; + + /// + /// Asynchronously returns a list of the documents matching the filter condition. + /// + /// + /// A LINQ expression filter. + Task> GetAllAsync(Expression> filter) where TDocument : IDocument; + + /// + /// Returns a list of the documents matching the filter condition. + /// + /// + /// A LINQ expression filter. + List GetAll(Expression> filter) where TDocument : IDocument; + + /// + /// Asynchronously counts how many documents match the filter condition. + /// + /// + /// A LINQ expression filter. + Task CountAsync(Expression> filter) where TDocument : IDocument; + + /// + /// Counts how many documents match the filter condition. + /// + /// + /// A LINQ expression filter. + long Count(Expression> filter) where TDocument : IDocument; + + #endregion Get + + #region Create + + /// + /// Asynchronously adds a document to the collection. + /// + /// + /// The document you want to add. + Task AddOneAsync(TDocument document) where TDocument : IDocument; + + /// + /// Adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// + /// The document you want to add. + void AddOne(TDocument document) where TDocument : IDocument; + + /// + /// Asynchronously adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// + /// The document you want to add. + Task AddManyAsync(IEnumerable documents) where TDocument : IDocument; + + /// + /// Adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// + /// The document you want to add. + void AddMany(IEnumerable documents) where TDocument : IDocument; + + #endregion + } + + public abstract class BaseMongoRepository : IBaseMongoRepository { public string ConnectionString { get; set; } public string DatabaseName { get; set; } @@ -25,130 +137,124 @@ namespace MongoDbGenericRepository protected IMongoDbContext _mongoDbContext = null; - #region Get + #region Read + /// - /// A generic GetOne method + /// Asynchronously returns one document given its id. /// /// - /// - /// - public async Task GetOne(string id) where TDocument : IDocument + /// The Id of the document you want to get. + public async Task GetById(Guid id) where TDocument : IDocument { var filter = Builders.Filter.Eq("Id", id); - return await GetOne(filter); + return await GetCollection().Find(filter).FirstOrDefaultAsync(); } /// - /// A generic GetOne method + /// Asynchronously returns one document given an expression filter. /// /// - /// - /// - public async Task GetOne(FilterDefinition filter) where TDocument : IDocument + /// A LINQ expression filter. + public async Task GetOneAsync(Expression> filter) where TDocument : IDocument { return await GetCollection().Find(filter).FirstOrDefaultAsync(); } /// - /// A generic get many method with filter + /// Returns one document given an expression filter. /// /// - /// - public async Task> GetAll(FilterDefinition filter) where TDocument : IDocument + /// A LINQ expression filter. + public TDocument GetOne(Expression> filter) where TDocument : IDocument + { + return GetCollection().Find(filter).FirstOrDefault(); + } + + /// + /// Returns a collection cursor. + /// + /// + /// A LINQ expression filter. + public IFindFluent GetCursor(Expression> filter) where TDocument : IDocument + { + return GetCollection().Find(filter); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// + /// A LINQ expression filter. + public async Task AnyAsync(Expression> filter) where TDocument : IDocument + { + var count = await GetCollection().CountAsync(filter); + return (count > 0); + } + + /// + /// Returns true if any of the document of the collection matches the filter condition. + /// + /// + /// A LINQ expression filter. + public bool Any(Expression> filter) where TDocument : IDocument + { + var count = GetCollection().Count(filter); + return (count > 0); + } + + /// + /// Asynchronously returns a list of the documents matching the filter condition. + /// + /// + /// A LINQ expression filter. + public async Task> GetAllAsync(Expression> filter) where TDocument : IDocument { return await GetCollection().Find(filter).ToListAsync(); } /// - /// FindCursor + /// Returns a list of the documents matching the filter condition. /// /// - /// - /// A cursor for the query - public IFindFluent FindCursor(FilterDefinition filter) where TDocument : IDocument + /// A LINQ expression filter. + public List GetAll(Expression> filter) where TDocument : IDocument { - var collection = GetCollection(); - var cursor = collection.Find(filter); - return cursor; + return GetCollection().Find(filter).ToList(); } /// - /// A generic get all method + /// Asynchronously counts how many documents match the filter condition. /// /// - /// - public async Task> GetAll() where TDocument : IDocument - { - var collection = GetCollection(); - return await collection.Find(new BsonDocument()).ToListAsync(); - } - - /// - /// A generic Exists method - /// - /// - /// - /// - public async Task Exists(string id) where TDocument : IDocument - { - var collection = GetCollection(); - var query = new BsonDocument("Id", id); - var cursor = collection.Find(query); - var count = await cursor.CountAsync(); - return (count > 0); - } - - /// - /// A generic count method - /// - /// - /// - /// - public async Task Count(string id) where TDocument : IDocument - { - var filter = new FilterDefinitionBuilder().Eq("Id", id); - return await Count(filter); - } - - /// - /// A generic count method - /// - /// - /// - /// - public async Task Count(FilterDefinition filter) where TDocument : IDocument - { - var collection = GetCollection(); - var cursor = collection.Find(filter); - var count = await cursor.CountAsync(); - return count; - } - - /// - /// A generic count method - /// - /// - /// - /// + /// A LINQ expression filter. public async Task CountAsync(Expression> filter) where TDocument : IDocument { - var collection = GetCollection(); - var cursor = collection.Find(filter); - var count = await cursor.CountAsync(); - return count; + return await GetCollection().CountAsync(filter); } /// - /// A generic count method + /// Counts how many documents match the filter condition. /// /// - /// - /// + /// A LINQ expression filter. public long Count(Expression> filter) where TDocument : IDocument { return GetCollection().Find(filter).Count(); } + /// + /// Asynchronously returns a paginated list of the documents matching the filter condition. + /// + /// + /// + /// The number of documents you want to skip. Default value is 0. + /// The number of documents you want to take. Default value is 50. + public async Task> GetPaginatedAsync(Expression> filter, int skipNumber = 0, int takeNumber = 50) where TDocument : IDocument + { + return await GetCollection().Find(filter).Skip(skipNumber).Limit(takeNumber).ToListAsync(); + } + + /// /// Returns a list of projected objects /// @@ -167,58 +273,73 @@ namespace MongoDbGenericRepository #endregion Get #region Create - /// - /// A generic Add One method async - /// - /// - /// - /// - public async Task AddOneAsync(TDocument item) where TDocument : IDocument - { - await GetCollection().InsertOneAsync(item); - } - /// - /// A generic method to add a document - /// - /// - /// - /// - public void AddOne(TDocument item) where TDocument : IDocument + + private void FormatDocument(TDocument document) where TDocument : IDocument { - if (item.Id == default(Guid)) + if (document.Id == default(Guid)) { - item.Id = Guid.NewGuid(); + document.Id = Guid.NewGuid(); } - if (item.AddedAtUtc == default(DateTime)) + if (document.AddedAtUtc == default(DateTime)) { - item.AddedAtUtc = DateTime.UtcNow; + document.AddedAtUtc = DateTime.UtcNow; } - - GetCollection().InsertOne(item); } /// - /// A generic Add Many method, performs a bulk insert in mongo + /// Asynchronously adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. /// /// - /// - /// - public async Task AddManyAsync(IEnumerable items) where TDocument : IDocument + /// The document you want to add. + public async Task AddOneAsync(TDocument document) where TDocument : IDocument { - await GetCollection().InsertManyAsync(items); + FormatDocument(document); + await GetCollection().InsertOneAsync(document); } /// - /// A generic Add Many method, performs a bulk insert in mongo + /// Adds a document to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. /// /// - /// - /// - public void AddMany(IEnumerable items) where TDocument : IDocument + /// The document you want to add. + public void AddOne(TDocument document) where TDocument : IDocument { - GetCollection().InsertMany(items); + FormatDocument(document); + GetCollection().InsertOne(document); + } + + /// + /// Asynchronously adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// + /// The document you want to add. + public async Task AddManyAsync(IEnumerable documents) where TDocument : IDocument + { + foreach (var document in documents) + { + FormatDocument(document); + } + await GetCollection().InsertManyAsync(documents); + } + + /// + /// Adds a list of documents to the collection. + /// Populates the Id and AddedAtUtc fields if necessary. + /// + /// + /// The document you want to add. + public void AddMany(IEnumerable documents) where TDocument : IDocument + { + foreach (var document in documents) + { + FormatDocument(document); + } + GetCollection().InsertMany(documents); } #endregion Create @@ -275,11 +396,57 @@ namespace MongoDbGenericRepository /// /// /// - public async Task DeleteMany(Expression> filter) where TDocument : IDocument + public async Task DeleteManyAsync(Expression> filter) where TDocument : IDocument { var deleteRes = await GetCollection().DeleteManyAsync(filter); return deleteRes.DeletedCount; } + + /// + /// A generic delete many method + /// + /// + /// + /// + public async Task DeleteManyAsync(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return 0; + } + var idsTodelete = documents.Select(e => e.Id).ToArray(); + var deleteRes = await GetCollection().DeleteManyAsync(x => idsTodelete.Contains(x.Id)); + return deleteRes.DeletedCount; + } + + /// + /// A generic delete many method + /// + /// + /// + /// + public long DeleteMany(IEnumerable documents) where TDocument : IDocument + { + if (!documents.Any()) + { + return 0; + } + var idsTodelete = documents.Select(e => e.Id).ToArray(); + var deleteRes = GetCollection().DeleteMany(x => idsTodelete.Contains(x.Id)); + return deleteRes.DeletedCount; + } + + /// + /// A generic delete many method + /// + /// + /// + /// + public long DeleteMany(Expression> filter) where TDocument : IDocument + { + var deleteRes = GetCollection().DeleteMany(filter); + return deleteRes.DeletedCount; + } #endregion Delete #region Update @@ -341,7 +508,6 @@ namespace MongoDbGenericRepository #endregion Find And Update - /// /// The private GetCollection method ///