From 759bcb1863e4e2734f16233a853006741b2bdcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Tue, 27 Mar 2018 14:29:48 +0300 Subject: [PATCH] Allow to get others collections in a mongodb repository easily --- .../Repositories/MongoDB/MongoDbRepository.cs | 18 ++++++----- .../Volo/Abp/MongoDB/AbpMongoDbContext.cs | 15 +++++++++ .../MongoDB/AbpMongoDbContextExtensions.cs | 17 ++++++++++ .../Volo/Abp/MongoDB/AbpMongoDbModule.cs | 2 +- .../Volo/Abp/MongoDB/IAbpMongoDbContext.cs | 7 ++++- .../Abp/MongoDB/IMongoDatabaseProvider.cs | 12 ------- .../Abp/MongoDB/IMongoDbContextProvider.cs | 8 +++++ .../Abp/Uow/MongoDB/MongoDbDatabaseApi.cs | 12 +++---- ...cs => UnitOfWorkMongoDbContextProvider.cs} | 31 +++++++++++-------- .../Abp/MongoDB/MongoDb_Repository_Tests.cs | 7 +++++ .../Abp/TestApp/MongoDb/CityRepository.cs | 10 +++--- .../TestApp/MongoDb/ITestAppMongoDbContext.cs | 6 +++- .../TestApp/MongoDb/TestAppMongoDbContext.cs | 9 ++++-- 13 files changed, 102 insertions(+), 52 deletions(-) create mode 100644 src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContextExtensions.cs delete mode 100644 src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDatabaseProvider.cs create mode 100644 src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs rename src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/{UnitOfWorkMongoDatabaseProvider.cs => UnitOfWorkMongoDbContextProvider.cs} (61%) diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index ba788d2498..bc05f1791a 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -13,17 +13,19 @@ namespace Volo.Abp.Domain.Repositories.MongoDB where TMongoDbContext : IAbpMongoDbContext where TEntity : class, IEntity { - public virtual string CollectionName => DatabaseProvider.DbContext.GetCollectionName(); + public virtual string CollectionName => DbContext.GetCollectionName(); - public virtual IMongoCollection Collection => Database.GetCollection(CollectionName); + public virtual IMongoCollection Collection => DbContext.Collection(); - public virtual IMongoDatabase Database => DatabaseProvider.GetDatabase(); + public virtual IMongoDatabase Database => DbContext.Database; - protected IMongoDatabaseProvider DatabaseProvider { get; } + public virtual TMongoDbContext DbContext => DbContextProvider.GetDbContext(); - public MongoDbRepository(IMongoDatabaseProvider databaseProvider) + protected IMongoDbContextProvider DbContextProvider { get; } + + public MongoDbRepository(IMongoDbContextProvider dbContextProvider) { - DatabaseProvider = databaseProvider; + DbContextProvider = dbContextProvider; } public override TEntity Insert(TEntity entity, bool autoSave = false) @@ -85,8 +87,8 @@ namespace Volo.Abp.Domain.Repositories.MongoDB where TMongoDbContext : IAbpMongoDbContext where TEntity : class, IEntity { - public MongoDbRepository(IMongoDatabaseProvider databaseProvider) - : base(databaseProvider) + public MongoDbRepository(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) { } diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs index 1ca2ae98fd..5b829c95c9 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContext.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using MongoDB.Driver; namespace Volo.Abp.MongoDB { @@ -8,10 +9,14 @@ namespace Volo.Abp.MongoDB { private static readonly MongoEntityMapping[] EmptyTypeList = new MongoEntityMapping[0]; + public IMongoDatabase Database { get; private set; } + private readonly Lazy> _mappingsByType; protected AbpMongoDbContext() { + //TODO: Cache model/mappings + _mappingsByType = new Lazy>(() => { return GetMappings().ToDictionary(m => m.EntityType); @@ -23,6 +28,11 @@ namespace Volo.Abp.MongoDB return EmptyTypeList; } + public virtual IMongoCollection Collection() + { + return Database.GetCollection(GetCollectionName()); + } + public virtual string GetCollectionName() { return GetMapping().CollectionName; @@ -38,5 +48,10 @@ namespace Volo.Abp.MongoDB return mapping; } + + public void InitializeDatabase(IMongoDatabase database) + { + Database = database; + } } } \ No newline at end of file diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContextExtensions.cs b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContextExtensions.cs new file mode 100644 index 0000000000..6a2fed67c7 --- /dev/null +++ b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbContextExtensions.cs @@ -0,0 +1,17 @@ +namespace Volo.Abp.MongoDB +{ + public static class AbpMongoDbContextExtensions + { + public static AbpMongoDbContext ToAbpMongoDbContext(this IAbpMongoDbContext dbContext) + { + var abpMongoDbContext = dbContext as AbpMongoDbContext; + + if (abpMongoDbContext == null) + { + throw new AbpException($"The type {dbContext.GetType().AssemblyQualifiedName} should be convertable to {typeof(AbpMongoDbContext).AssemblyQualifiedName}!"); + } + + return abpMongoDbContext; + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs index 1125d178b2..c4712065aa 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs @@ -11,7 +11,7 @@ namespace Volo.Abp.MongoDB { public override void ConfigureServices(IServiceCollection services) { - services.TryAddTransient(typeof(IMongoDatabaseProvider<>), typeof(UnitOfWorkMongoDatabaseProvider<>)); + services.TryAddTransient(typeof(IMongoDbContextProvider<>), typeof(UnitOfWorkMongoDbContextProvider<>)); services.AddAssemblyOf(); } } diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IAbpMongoDbContext.cs b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IAbpMongoDbContext.cs index eb26082356..13851e40a6 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IAbpMongoDbContext.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IAbpMongoDbContext.cs @@ -1,11 +1,16 @@ using System.Collections.Generic; +using MongoDB.Driver; namespace Volo.Abp.MongoDB { public interface IAbpMongoDbContext { - IReadOnlyList GetMappings(); + IMongoDatabase Database { get; } + + IMongoCollection Collection(); string GetCollectionName(); + + IReadOnlyList GetMappings(); //TODO: Consider to remove from the interface } } \ No newline at end of file diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDatabaseProvider.cs b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDatabaseProvider.cs deleted file mode 100644 index e083f4786b..0000000000 --- a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDatabaseProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MongoDB.Driver; - -namespace Volo.Abp.MongoDB -{ - public interface IMongoDatabaseProvider - where TMongoDbContext : IAbpMongoDbContext - { - TMongoDbContext DbContext { get; } - - IMongoDatabase GetDatabase(); - } -} \ No newline at end of file diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs new file mode 100644 index 0000000000..9f89054dcc --- /dev/null +++ b/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoDbContextProvider.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.MongoDB +{ + public interface IMongoDbContextProvider + where TMongoDbContext : IAbpMongoDbContext + { + TMongoDbContext GetDbContext(); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/MongoDbDatabaseApi.cs b/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/MongoDbDatabaseApi.cs index 01186c040b..bb02ad0108 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/MongoDbDatabaseApi.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/MongoDbDatabaseApi.cs @@ -1,14 +1,12 @@ -using MongoDB.Driver; - -namespace Volo.Abp.Uow.MongoDB +namespace Volo.Abp.Uow.MongoDB { - public class MongoDbDatabaseApi : IDatabaseApi + public class MongoDbDatabaseApi : IDatabaseApi { - public IMongoDatabase Database { get; } + public TMongoDbContext DbContext { get; } - public MongoDbDatabaseApi(IMongoDatabase database) + public MongoDbDatabaseApi(TMongoDbContext dbContext) { - Database = database; + DbContext = dbContext; } } } diff --git a/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDatabaseProvider.cs b/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs similarity index 61% rename from src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDatabaseProvider.cs rename to src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs index 86d9a4785a..faf0c89820 100644 --- a/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDatabaseProvider.cs +++ b/src/Volo.Abp.MongoDB/Volo/Abp/Uow/MongoDB/UnitOfWorkMongoDbContextProvider.cs @@ -1,28 +1,25 @@ -using MongoDB.Driver; +using Microsoft.Extensions.DependencyInjection; +using MongoDB.Driver; using Volo.Abp.Data; using Volo.Abp.MongoDB; namespace Volo.Abp.Uow.MongoDB { - public class UnitOfWorkMongoDatabaseProvider : IMongoDatabaseProvider + public class UnitOfWorkMongoDbContextProvider : IMongoDbContextProvider where TMongoDbContext : IAbpMongoDbContext { - public TMongoDbContext DbContext { get; } - private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IConnectionStringResolver _connectionStringResolver; - public UnitOfWorkMongoDatabaseProvider( + public UnitOfWorkMongoDbContextProvider( IUnitOfWorkManager unitOfWorkManager, - IConnectionStringResolver connectionStringResolver, - TMongoDbContext dbContext) + IConnectionStringResolver connectionStringResolver) { _unitOfWorkManager = unitOfWorkManager; _connectionStringResolver = connectionStringResolver; - DbContext = dbContext; } - public IMongoDatabase GetDatabase() + public TMongoDbContext GetDbContext() { var unitOfWork = _unitOfWorkManager.Current; if (unitOfWork == null) @@ -48,11 +45,19 @@ namespace Volo.Abp.Uow.MongoDB //TODO: Create only single MongoDbClient per connection string in an application (extract MongoClientCache for example). var databaseApi = unitOfWork.GetOrAddDatabaseApi( dbContextKey, - () => new MongoDbDatabaseApi( - new MongoClient(connectionString).GetDatabase(databaseName) - )); + () => + { + var database = new MongoClient(connectionString).GetDatabase(databaseName); - return ((MongoDbDatabaseApi)databaseApi).Database; + var dbContext = unitOfWork.ServiceProvider.GetRequiredService(); + + var abpDbContext = unitOfWork.ServiceProvider.GetRequiredService().ToAbpMongoDbContext(); + abpDbContext.InitializeDatabase(database); + + return new MongoDbDatabaseApi(dbContext); + }); + + return ((MongoDbDatabaseApi)databaseApi).DbContext; } } } \ No newline at end of file diff --git a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDb_Repository_Tests.cs b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDb_Repository_Tests.cs index 2fc5a853fa..56127cc42f 100644 --- a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDb_Repository_Tests.cs +++ b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/MongoDb_Repository_Tests.cs @@ -90,5 +90,12 @@ namespace Volo.Abp.MongoDB city.ShouldNotBeNull(); city.Name.ShouldBe("Istanbul"); } + + [Fact] + public async Task Should_Access_To_Other_Collections_In_Same_Context_In_A_Custom_Method() + { + var people = await _cityRepository.GetPeopleInTheCityAsync("London"); + people.Count.ShouldBeGreaterThan(0); + } } } diff --git a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs index f9bdbec39a..b122cad86e 100644 --- a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs +++ b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/CityRepository.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using MongoDB.Driver; +using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; using Volo.Abp.TestApp.Domain; @@ -10,8 +11,8 @@ namespace Volo.Abp.TestApp.MongoDb { public class CityRepository : MongoDbRepository, ICityRepository { - public CityRepository(IMongoDatabaseProvider databaseProvider) - : base(databaseProvider) + public CityRepository(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) { } @@ -24,10 +25,7 @@ namespace Volo.Abp.TestApp.MongoDb public async Task> GetPeopleInTheCityAsync(string cityName) { var city = await FindByNameAsync(cityName); - - throw new NotImplementedException(); - - //return await DbContext.People.Where(p => p.CityId == city.Id).ToListAsync(); + return await DbContext.People.AsQueryable().Where(p => p.CityId == city.Id).ToListAsync(); } } } diff --git a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/ITestAppMongoDbContext.cs b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/ITestAppMongoDbContext.cs index 2b0a01eed1..88682918cb 100644 --- a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/ITestAppMongoDbContext.cs +++ b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/ITestAppMongoDbContext.cs @@ -1,11 +1,15 @@ -using Volo.Abp.Data; +using MongoDB.Driver; +using Volo.Abp.Data; using Volo.Abp.MongoDB; +using Volo.Abp.TestApp.Domain; namespace Volo.Abp.TestApp.MongoDb { [ConnectionStringName("TestApp")] public interface ITestAppMongoDbContext : IAbpMongoDbContext { + IMongoCollection People { get; } + IMongoCollection Cities { get; } } } \ No newline at end of file diff --git a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs index 7e6f366754..8245676f24 100644 --- a/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs +++ b/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs @@ -9,11 +9,14 @@ namespace Volo.Abp.TestApp.MongoDb [ConnectionStringName("TestApp")] public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext { - public IMongoCollection People { get; set; } + //TODO: We can set collections automatically, lik EF Core + //TODO: We can get collection names conventionally, or by an attribute - public IMongoCollection Cities { get; set; } + public IMongoCollection People => Collection(); - //TODO: Default implementation should read mogo collections from the context! + public IMongoCollection Cities => Collection(); + + //TODO: Default implementation should read IMongoCollections from the context! //GetMappings should send a context and we add to it. Rename to ConfigureMappings. public override IReadOnlyList GetMappings()