Base solution for your next web application
Open Closed

EntityHistory and Mongodb #5282


User avatar
0
BobIngham created

In my [Projectname]CoreModule I replace IEntityHistoryStore with MongodbEntityHistoryStore:

Configuration.ReplaceService<IEntityHistoryStore, MongodbEntityHistoryStore>(DependencyLifeStyle.Transient);

. I implement MongodbEntityHistoryStore in the Core project:

using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.EntityHistory;
using Abp.Timing;
using MongoDB.Bson;
using MongoDB.Driver;
using Nuagecare.Mongodb;
using Nuagecare.MultiTenancy;
using System;
using System.Threading.Tasks;

namespace Nuagecare.App.Mongodb
{
    /// <summary>
    /// Implements <see cref="IEntityHistoryStore"/> to save entity change informations to Mongodb.
    /// </summary>
    public class MongodbEntityHistoryStore : IEntityHistoryStore, ITransientDependency
    {
        private readonly IRepository<EntityChangeSet, long> _changeSetRepository;
        private readonly TenantManager _tenantManager;

        /// <summary>
        /// MongodbEntityHistoryStore
        /// </summary>
        public MongodbEntityHistoryStore(
            IRepository<EntityChangeSet, long> changeSetRepository,
            TenantManager tenantManager)
        {
            _changeSetRepository = changeSetRepository;
            _tenantManager = tenantManager;
        }

        public async Task SaveAsync(EntityChangeSet changeSet)
        {
            var mongoClient = new MongodbConfig().Initialize();
            IMongoDatabase db = mongoClient.GetDatabase(await GetTenancyNameFromTenantId(Convert.ToInt32(changeSet.TenantId)));
            var collection = db.GetCollection<BsonDocument>("entityChangeSets");
            var document = changeSet.ToBsonDocument();
            document.Set("_id", ObjectId.GenerateNewId());
            document.Set("CreationTime", Clock.Now);
            await collection.InsertOneAsync(document);
        }

        private async Task<string> GetTenancyNameFromTenantId(int tenantId)
        {
            var tenant = await _tenantManager.FindByIdAsync(tenantId);
            if (tenant == null)
            {
                return "Projectname";
            }
            return tenant.TenancyName;
        }
    }
}

This works great, my entity history data is now in Mongodb and all of my tenants have their own Mongodb database (user rights are set during the create tenant method). Now I need to read the data so I copy the code for AuditLogAppService and refactor it as MongodbAuditLogAppService which is placed in my Application project. I try register my new service in [Projectname]ApplicationModule:

IocManager.Register<IAuditLogAppService, MongodbAuditLogAppService>(DependencyLifeStyle.Transient);

, rebuild, run swagger, but the app still goes to AuditLogAppService. I have also tried register in [Projectname]WebHostModule to no avail.

What do I need to do to register and inject MongodbAuditLogAppService instead of Zero's standard AuditLogAppService?


5 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Similar to how you replaced IEntityHistoryStore.

    Configuration.ReplaceService<IAuditLogAppService, MongodbAuditLogAppService>(DependencyLifeStyle.Transient);
    
  • User Avatar
    0
    BobIngham created

    Which module should this code go in? I try place in [Projectname]ApplicationModule in the Application project and get "The non-generic method 'IAppStartupConfiguration.ReplaceService(Type, Action) cannot be used with type arguments". I place in [Projectname]WebCoreModule in the Web.Core project and nothing happens, AuditLogService is still called. It can not be placed in the [Projectname]CoreModule in the Core project because of dependencies.

  • User Avatar
    0
    alper created
    Support Team

    This is another way of overriding an implementation. Take a try.

    Configuration.IocManager.IocContainer.Register(Component.For<IAuditLogAppService>().Instance(MongodbAuditLogAppService).IsDefault());
    

    <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/issues/983">https://github.com/aspnetboilerplate/as ... issues/983</a>

  • User Avatar
    0
    BobIngham created

    "MongodbAuditLogAppService" is a type which is not valid in the current context. I also tried:

    Configuration.ReplaceService(typeof(IAuditLogAppService), () =>
    {
        IocManager.IocContainer.Register(
            Component.For<IAuditLogAppService>()
                .ImplementedBy<MongodbAuditLogAppService>()
                .LifestyleTransient()
            );
    });
    

    I have used a few IoC containers, I confess to not understanding the hieroglyphics of lifetimes but....

    Why is so hard to simply replace a Zero service with my own service?

  • User Avatar
    0
    aaron created
    Support Team
    using Abp.Configuration.Startup;