Starts in:
0 DAY
10 HRS
51 MIN
53 SEC
Starts in:
0 D
10 H
51 M
53 S
Open Closed

OrganizationUnit Update events are not published #7412


User avatar
0
WaelRazouk created
  • ABP Framework version: v8.1.1
  • UI Type: Angular
  • Database System: EF Core (SQL Server)
  • Tiered (for MVC) or Auth Server Separated (for Angular): yes
  • Exception message and full stack trace:
  • Steps to reproduce the issue:

I have the micro-service architecture.

Follow the steps described in https://docs.abp.io/en/abp/latest/Distributed-Event-Bus#entity-synchronizer and try to synchronize OrganizationUnit (so I can have a replica of the table in my custom service)

Here is the synchronizer class


public class CssDepartmentSynchronizer :
    EntitySynchronizer<CssDepartment, OrganizationUnitEto>
{

    private readonly ILogger<CssDepartmentSynchronizer> _logger;

    public CssDepartmentSynchronizer(
        IObjectMapper objectMapper, 
        IRepository<CssDepartment> repository,
        ILogger<CssDepartmentSynchronizer> logger) : base(objectMapper, repository)
    {
        _logger = logger;
    }

    public override Task HandleEventAsync(EntityCreatedEto<OrganizationUnitEto> eventData)
    {
        _logger.LogInformation("CssDepartmentSynchronizer EntityCreatedEto");
        return base.HandleEventAsync(eventData);
    }

    public override Task HandleEventAsync(EntityDeletedEto<OrganizationUnitEto> eventData)
    {
        _logger.LogInformation("CssDepartmentSynchronizer EntityDeletedEto");
        return base.HandleEventAsync(eventData);
    }

    public override Task HandleEventAsync(EntityUpdatedEto<OrganizationUnitEto> eventData)
    {
        _logger.LogInformation("CssDepartmentSynchronizer EntityUpdatedEto");
        return base.HandleEventAsync(eventData);
    }

    protected override async Task<CssDepartment?> FindLocalEntityAsync(OrganizationUnitEto eto)
    {
        _logger.LogInformation("CssDepartmentSynchronizer FindLocalEntityAsync");
        var entity = await Repository.FindAsync(d => d.Id  == eto.Id);
        if (entity == null)
            _logger.LogInformation("CssDepartmentSynchronizer not found");
        else
            _logger.LogInformation("CssDepartmentSynchronizer found");
        return entity;
    }
}

This class is not being hit (no logs added to the logs file). Similar code for IdentityUser works fine

public class CssUserSynchronizer :
 EntitySynchronizer<CssUser, UserEto>

8 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Did you configure the AutoEventSelectors

    Configure<AbpDistributedEntityEventOptions>(options =>
    {
        options.AutoEventSelectors.Add<OrganizationUnit>();
        options.EtoMappings.Add<OrganizationUnit, OrganizationUnitEto>();
    });
    
  • User Avatar
    0
    WaelRazouk created

    Hi,

    Did you configure the AutoEventSelectors

    Configure<AbpDistributedEntityEventOptions>(options => 
    { 
        options.AutoEventSelectors.Add<OrganizationUnit>(); 
        options.EtoMappings.Add<OrganizationUnit, OrganizationUnitEto>(); 
    }); 
    

    Hi, yes in my DomainModule, here is the ConfigureServices method

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        base.ConfigureServices(context);
        Configure<AbpDistributedEntityEventOptions>(options =>
        {
            options.AutoEventSelectors.Add<OrganizationUnit>();
            options.EtoMappings.Add<OrganizationUnit, OrganizationUnitEto>();
        });
    }
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    I will check it

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    It works for me

    My steps:

    • Create a ms template via suite
    • Configure AbpDistributedEntityEventOptions in the IdentityServiceDomainModule
    Configure<AbpDistributedEntityEventOptions>(options =>
    {
        options.AutoEventSelectors.Add<OrganizationUnit>();
        options.EtoMappings.Add<OrganizationUnit, OrganizationUnitEto>();
    });
    
    • Add CssDepartmentSynchronizer to ProductService
    public class CssDepartmentSynchronizer :
        EntitySynchronizer<Product, OrganizationUnitEto>
    {
    
        private readonly ILogger<CssDepartmentSynchronizer> _logger;
    
        public CssDepartmentSynchronizer(
            IObjectMapper objectMapper, 
            IRepository<Product> repository,
            ILogger<CssDepartmentSynchronizer> logger) : base(objectMapper, repository)
        {
            _logger = logger;
        }
    
        public override Task HandleEventAsync(EntityCreatedEto<OrganizationUnitEto> eventData)
        {
            _logger.LogInformation("CssDepartmentSynchronizer EntityCreatedEto");
            //return base.HandleEventAsync(eventData);
            return Task.CompletedTask;
        }
    
        public override Task HandleEventAsync(EntityDeletedEto<OrganizationUnitEto> eventData)
        {
            _logger.LogInformation("CssDepartmentSynchronizer EntityDeletedEto");
            //return base.HandleEventAsync(eventData);
            return Task.CompletedTask;
        }
    
        public override Task HandleEventAsync(EntityUpdatedEto<OrganizationUnitEto> eventData)
        {
            _logger.LogInformation("CssDepartmentSynchronizer EntityUpdatedEto");
            //return base.HandleEventAsync(eventData);
            return Task.CompletedTask;
        }
    
        protected override async Task<Product?> FindLocalEntityAsync(OrganizationUnitEto eto)
        {
            _logger.LogInformation("CssDepartmentSynchronizer FindLocalEntityAsync");
            var entity = await Repository.FindAsync(d => d.Id  == eto.Id);
            if (entity == null)
                _logger.LogInformation("CssDepartmentSynchronizer not found");
            else
                _logger.LogInformation("CssDepartmentSynchronizer found");
            return entity;
        }
    }
    

  • User Avatar
    0
    WaelRazouk created

    Hi, It works now (because I moved the AbpDistributedEntityEventOptions to the IdentityServiceDomainModule project ( I was setting it in my service domain project previously.

    But I still have an issue: OrganizationUnitEto doesn't have ParentId property like OrganizationUnit and I need to know this property to save it in my db table. When I try to get the OrganizationUnit entity using IOrganizationUnitRepository I get the following error: [ERR] An error occurred using the connection to database '' on server ''.

    Stacktrace: 2024-07-01 11:00:47.184 +03:00 [ERR] An error occurred using the connection to database '' on server ''. 2024-07-01 11:00:47.192 +03:00 [ERR] An exception occurred while iterating over the results of a query for context type 'RMG.Iso20.IdentityService.EntityFrameworkCore.IdentityServiceDbContext'. System.InvalidOperationException: The ConnectionString property has not been initialized. at Microsoft.Data.SqlClient.SqlConnection.PermissionDemand() at Microsoft.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection) at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry, SqlConnectionOverrides overrides) at Microsoft.Data.SqlClient.SqlConnection.InternalOpenAsync(CancellationToken cancellationToken) --- End of stack trace from previous location --- at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 operation, Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable1.AsyncEnumerator.MoveNextAsync() System.InvalidOperationException: The ConnectionString property has not been initialized. at Microsoft.Data.SqlClient.SqlConnection.PermissionDemand() at Microsoft.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection) at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry, SqlConnectionOverrides overrides) at Microsoft.Data.SqlClient.SqlConnection.InternalOpenAsync(CancellationToken cancellationToken) --- End of stack trace from previous location --- at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 operation, Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable1.AsyncEnumerator.MoveNextAsync()

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can add your MyOrganizationUnitEto to override the OrganizationUnitEto.

    public class MyOrganizationUnitEto
    {
        public Guid? ParentId { get; set}
        ....
        
    }
    
    ....
    
    CreateMap<OrganizationUnit, MyOrganizationUnitEto>();
    ....
    
    Configure<AbpDistributedEntityEventOptions>(options =>
    {
        options.AutoEventSelectors.Add<OrganizationUnit>();
        options.EtoMappings.RemoveAll(x => x.Value.EtoType == typeof(OrganizationUnitEto);
        options.EtoMappings.Add<OrganizationUnit, MyOrganizationUnitEto>(typeof(AbpIdentityDomainModule));
    });
    

    I will add the ParentId to OrganizationUnitEto in the next version https://github.com/abpframework/abp/issues/20136

  • User Avatar
    0
    WaelRazouk created

    Can you confirm where did you add this code?

    Configure<AbpDistributedEntityEventOptions>(options =>
    {
        options.AutoEventSelectors.Add<OrganizationUnit>();
        options.EtoMappings.RemoveAll(x => x.Value.EtoType == typeof(OrganizationUnitEto));
        options.EtoMappings.Add<OrganizationUnit, CustomOrganizationUnitEto>(typeof(AbpIdentityDomainModule));
    });
    

    In which project and service. Because for me It only worked under IdentityService And based on this: I need to define new AutoMapper profile in the IdentityService to map this

    CreateMap<OrganizationUnit, MyOrganizationUnitEto>();
    

    Am I right? or did I miss something?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Add to the IdentityServiceDomainModule

Made with ❤️ on ABP v9.1.0-preview. Updated on November 20, 2024, 13:06