Open Closed

Unit Of Work Error #8291


User avatar
0
Teknosol created
  • ABP Framework version: v7.1.1
  • Database System: EF Core (PostgreSQL, )
  • Exception message and full stack trace:
  • Steps to reproduce the issue:

I created a custom worker service. When I call the insertasync method from the domain manager class, I get this error. How can ı fix this error?


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

    Hi,

    could you share your method code and the full error logs?

  • User Avatar
    0
    Teknosol created

    Thanks for your feedback,

    Below are the code blocks, if you share your email address I can send you the project.

    This class is I call insertasync();

    public class ScreenRootManager : DomainService
    {
        private readonly IScreenDesignRepository _screenDesignRepository;
        private readonly IObjectMapper _mapper;
        private readonly ILogger<ScreenRootManager> _logger;
    
    
    
        public ScreenRootManager(IScreenDesignRepository screenDesignRepository, IObjectMapper mapper, IUnitOfWorkManager unitOfWorkManager, ILogger<ScreenRootManager> logger)
        {
            var screenDesignRepository1 = screenDesignRepository;
            _screenDesignRepository = screenDesignRepository;
            _mapper = mapper;
            _logger = logger;
        }
    
        public async Task<ScreenDesignCreateResult> CreateAsync(
          IScreenDesignCreateCommand screenDesignDto
      )
        {
    
    
                var screenDesign = new ScreenDesign(
                screenDesignDto.Type,
                screenDesignDto.ProgramName,
            Guid.NewGuid(),
               screenDesignDto.FieldId,
               screenDesignDto.FieldName,
              screenDesignDto.FieldDescription,
               screenDesignDto.GridJsonHeader,
               screenDesignDto.TabJsonHeader,
              screenDesignDto.PopupOrderAppearance,
    
               screenDesignDto.TabSequence,
    
               screenDesignDto.DontShow,
               screenDesignDto.IsMandatoryField,
               screenDesignDto.AllowMinusDataEntry,
               screenDesignDto.DontRefreshDataAfterRegistration,
               screenDesignDto.CanNotChangeFieldWithEdit,
               screenDesignDto.AllowFiltering,
               screenDesignDto.IsPrimary,
               screenDesignDto.Alignment,
               screenDesignDto.Format,
               screenDesignDto.Width,
               screenDesignDto.MessageKey,
               screenDesignDto.LookupUrl,
               screenDesignDto.IsGrid,
               screenDesignDto.HeaderUrl,
               screenDesignDto.DataSourceUrl,
               screenDesignDto.TabTitle,
               screenDesignDto.TemplateName,
               screenDesignDto.PropertyDataType,
               screenDesignDto.DisplayLocation,
               screenDesignDto.SubTab,
               screenDesignDto.SubTabSequence,
               screenDesignDto.DataLength,
               screenDesignDto.ColumnOrder,
               screenDesignDto.DefaultOrder,
               screenDesignDto.NotAllowChangesNotBlank,
              screenDesignDto.MinimumCharLength,
               screenDesignDto.MaximumCharLength,
               screenDesignDto.IsTree,
               screenDesignDto.RelationField,
               screenDesignDto.CascadeFrom,
               screenDesignDto.IsDMS,
               screenDesignDto.IsDMSEnum
            );
            try
            {
                var data = await _screenDesignRepository.InsertAsync(screenDesign);
                var returnDto = _mapper.Map<ScreenDesign, ScreenDesignCreateResult>(data);
    
                return returnDto ;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "error occured");
    
                throw;
            }
        }
    
    
    }
    

    I consume this class with AMQP and direct it to the manager, that is, to the upper class, I trigger the method with this class and use mass transit.

    public class CreateScreenDesignConsumer : IConsumer<IScreenDesignCreateCommand>
    {
        private readonly ScreenRootManager _screenRootManager;
        private readonly ILogger<CreateScreenDesignConsumer> _logger;
    
        public CreateScreenDesignConsumer(ScreenRootManager screenRootManager, ILogger<CreateScreenDesignConsumer> logger)
        {
            _screenRootManager = screenRootManager;
            _logger = logger;
        }
    
        public async Task Consume(ConsumeContext<IScreenDesignCreateCommand> context)
        {
    
            try
            {
                var result = await _screenRootManager.CreateAsync(context.Message);
                await context.RespondAsync(new Result<ScreenDesignCreateResult>(data: result));
            }
            catch (Exception ex)
            {
                await context.RespondAsync<Fault<Result>>
              (new { Message = "ScreenDeisgn:CreateFail", FaultMessage = ex.Message, FaultStackTrace = ex.StackTrace });
    
            }
        }
    }
    

    This class is where I implemented the efcore layer in the worker service;

    IHost host = Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
            logging.AddDebug(); // Optional: Adds debug logging
        })
        .ConfigureServices(async (hostContext, services) =>
        {
            var configuration = hostContext.Configuration;
            var builder = Host.CreateDefaultBuilder(args);
    
            //I added the classes in quotes because generic methods were not shown.
            "await services.AddApplicationAsync"AbpAutofacModule"();"
            "await services.AddApplicationAsync"ScreenDesignEntityFrameworkCoreModule" ();"
    
            services.AddMassTransit(x =>
            {
                x.AddConsumer<CreateScreenDesignConsumer>();
    
                x.UsingRabbitMq((context, cfg) =>
                {
                    cfg.Host("amqps://localhost/", h =>
                    {
                        h.Username("localhost");
                        h.Password("");
                    });
    
                    cfg.ConfigureEndpoints(context);
                });
            });
    
            services.AddHostedService<Worker>();
        })
        .Build();
    
    host.Run();
    
    

    Error logs here; info: ScreenDesign.Domain.Worker.Worker[0] Worker running at: 11/18/2024 09:08:18 +03:00 fail: ScreenDesign.ScreenRootManager[0] error occured Volo.Abp.AbpException: A DbContext can only be created inside a unit of work! at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider1.GetDbContextAsync() at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository2.InsertAsync(TEntity entity, Boolean autoSave, CancellationToken cancellationToken) at ScreenDesign.ScreenRootManager.CreateAsync(IScreenDesignCreateCommand screenDesignDto) in C:\Users\ali.ozen\Desktop\ddd\18.11-1\ScreenDesign\src\ScreenDesign.Domain\ScreenRootManager.cs:line 89 info: ScreenDesign.Domain.Worker.Worker[0] Worker running at: 11/18/2024 09:08:21 +03:00 fail: ScreenDesign.Domain.Worker.Consumers.CreateScreenDesignConsumer[0] error occured Volo.Abp.AbpException: A DbContext can only be created inside a unit of work! at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider1.GetDbContextAsync() at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository2.InsertAsync(TEntity entity, Boolean autoSave, CancellationToken cancellationToken) at ScreenDesign.ScreenRootManager.CreateAsync(IScreenDesignCreateCommand screenDesignDto) in C:\Users\ali.ozen\Desktop\ddd\18.11-1\ScreenDesign\src\ScreenDesign.Domain\ScreenRootManager.cs:line 89 at ScreenDesign.Domain.Worker.Consumers.CreateScreenDesignConsumer.Consume(ConsumeContext1 context) in C:\Users\ali.ozen\Desktop\ddd\18.11-1\ScreenDesign\ScreenDesign.Domain.Worker\Consumers\CreateScreenDesignConsumer.cs:line 31 fail: MassTransit.ReceiveTransport[0] R-FAULT rabbitmqs://cow.rmq2.cloudamqp.com/gouvefqf/CreateScreenDesign a0570000-0faa-0009-898d-08dd07975edf ScreenDesign.Commands.IScreenDesignCreateCommand ScreenDesign.Domain.Worker.Consumers.CreateScreenDesignConsumer(00:00:14.3431337) Volo.Abp.AbpException: A DbContext can only be created inside a unit of work! at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider1.GetDbContextAsync() at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository2.InsertAsync(TEntity entity, Boolean autoSave, CancellationToken cancellationToken) at ScreenDesign.ScreenRootManager.CreateAsync(IScreenDesignCreateCommand screenDesignDto) in C:\Users\ali.ozen\Desktop\ddd\18.11-1\ScreenDesign\src\ScreenDesign.Domain\ScreenRootManager.cs:line 89 at ScreenDesign.Domain.Worker.Consumers.CreateScreenDesignConsumer.Consume(ConsumeContext1 context) in C:\Users\ali.ozen\Desktop\ddd\18.11-1\ScreenDesign\ScreenDesign.Domain.Worker\Consumers\CreateScreenDesignConsumer.cs:line 31 at MassTransit.DependencyInjection.ScopeConsumerFactory1.Send[TMessage](ConsumeContext1 context, IPipe1 next) in //src/MassTransit/DependencyInjection/DependencyInjection/ScopeConsumerFactory.cs:line 22 at MassTransit.DependencyInjection.ScopeConsumerFactory1.Send[TMessage](ConsumeContext1 context, IPipe1 next) in /_/src/MassTransit/DependencyInjection/DependencyInjection/ScopeConsumerFactory.cs:line 22 at MassTransit.Middleware.ConsumerMessageFilter2.MassTransit.IFilter<MassTransit.ConsumeContext<TMessage>>.Send(ConsumeContext1 context, IPipe1 next) in //src/MassTransit/Middleware/ConsumerMessageFilter.cs:line 48 info: ScreenDesign.Domain.Worker.Worker[0] Worker running at: 11/18/2024 09:08:22 +03:00`

    Error log Screenshot;

  • User Avatar
    0
    Teknosol created

    You can download my project from this link: https://we.tl/t-EWOKy9gh2H

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Here are some requirements for using unit of work

    See https://abp.io/docs/latest/framework/architecture/domain-driven-design/unit-of-work#controlling-the-unit-of-work

  • User Avatar
    0
    Teknosol created

    Thank you for your answer, I added the codes you said as below but the same problem persists. Did you have a chance to review my project?

    My scenario works like this: I want to capture the data with mass transit in the worker service and save it to the db, I created the worker service myself, the API where the data is created only sends the ScreenDesignCreateCommand(like dto) object.

     using Microsoft.Extensions.Localization;
    using Microsoft.Extensions.Logging;
    using ScreenDesign.Commands;
    using ScreenDesign.Helper;
    using ScreenDesign.Localization;
    using ScreenDesign.Results;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Domain.Entities;
    using Volo.Abp.Domain.Services;
    using Volo.Abp.ObjectMapping;
    using Volo.Abp.Uow;
    
    namespace ScreenDesign
    {
        public interface IScreenRootManager
        {
            Task<ScreenDesignCreateResult> CreateAsync(IScreenDesignCreateCommand screenDesignDto);
        }
        public class ScreenRootManager : DomainService, ITransientDependency, IUnitOfWorkEnabled , IScreenRootManager
        {
            private readonly IScreenDesignRepository _screenDesignRepository;
            private readonly IObjectMapper _mapper;
            private readonly ILogger<ScreenRootManager> _logger;
    
    
    
            public ScreenRootManager(IScreenDesignRepository screenDesignRepository, IObjectMapper mapper, IUnitOfWorkManager unitOfWorkManager, ILogger<ScreenRootManager> logger)
            {
                var screenDesignRepository1 = screenDesignRepository;
                _screenDesignRepository = screenDesignRepository;
                _mapper = mapper;
                _logger = logger;
            }
    
            public async Task<ScreenDesignCreateResult> CreateAsync(
              IScreenDesignCreateCommand screenDesignDto
          )
            {
    
    
                    var screenDesign = new ScreenDesign(
                    screenDesignDto.Type,
                    screenDesignDto.ProgramName,
                Guid.NewGuid(),
                   screenDesignDto.FieldId,
                   screenDesignDto.FieldName,
                  screenDesignDto.FieldDescription,
                   screenDesignDto.GridJsonHeader,
                   screenDesignDto.TabJsonHeader,
                  screenDesignDto.PopupOrderAppearance,
    
                   screenDesignDto.TabSequence,
    
                   screenDesignDto.DontShow,
                   screenDesignDto.IsMandatoryField,
                   screenDesignDto.AllowMinusDataEntry,
                   screenDesignDto.DontRefreshDataAfterRegistration,
                   screenDesignDto.CanNotChangeFieldWithEdit,
                   screenDesignDto.AllowFiltering,
                   screenDesignDto.IsPrimary,
                   screenDesignDto.Alignment,
                   screenDesignDto.Format,
                   screenDesignDto.Width,
                   screenDesignDto.MessageKey,
                   screenDesignDto.LookupUrl,
                   screenDesignDto.IsGrid,
                   screenDesignDto.HeaderUrl,
                   screenDesignDto.DataSourceUrl,
                   screenDesignDto.TabTitle,
                   screenDesignDto.TemplateName,
                   screenDesignDto.PropertyDataType,
                   screenDesignDto.DisplayLocation,
                   screenDesignDto.SubTab,
                   screenDesignDto.SubTabSequence,
                   screenDesignDto.DataLength,
                   screenDesignDto.ColumnOrder,
                   screenDesignDto.DefaultOrder,
                   screenDesignDto.NotAllowChangesNotBlank,
                  screenDesignDto.MinimumCharLength,
                   screenDesignDto.MaximumCharLength,
                   screenDesignDto.IsTree,
                   screenDesignDto.RelationField,
                   screenDesignDto.CascadeFrom,
                   screenDesignDto.IsDMS,
                   screenDesignDto.IsDMSEnum
                );
                try
                {
                    var data = await _screenDesignRepository.InsertAsync(screenDesign);
                    var returnDto = _mapper.Map<ScreenDesign, ScreenDesignCreateResult>(data);
    
                    return returnDto ;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "error occured");
    
                    throw;
                }
            }
    
    
        }
    }
    
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can try this:

    public class CreateScreenDesignConsumer : IConsumer<IScreenDesignCreateCommand>
    {
        private readonly IScreenRootManager _screenRootManager;
        private readonly ILogger<CreateScreenDesignConsumer> _logger;
    
        public CreateScreenDesignConsumer(IScreenRootManager screenRootManager, ILogger<CreateScreenDesignConsumer> logger)
        {
            _screenRootManager = screenRootManager;
            _logger = logger;
        }
    
        public virtual async Task Consume(ConsumeContext<IScreenDesignCreateCommand> context)
        {
    
            try
            {
                var result = await _screenRootManager.CreateAsync(context.Message);
                await context.RespondAsync(new Result<ScreenDesignCreateResult>(data: result));
            }
            catch (Exception ex)
            {
                await context.RespondAsync<Fault<Result>>
              (new { Message = "ScreenDeisgn:CreateFail", FaultMessage = ex.Message, FaultStackTrace = ex.StackTrace });
    
            }
        }
    }
    
  • User Avatar
    0
    Teknosol created

    Thank you for your answer, But the error persists. Is there another way you can suggest?

    I edited what you said as follows;

    public interface IScreenRootManager
    {
        Task<ScreenDesignCreateResult> CreateAsync(IScreenDesignCreateCommand screenDesignDto);
    }
    public class ScreenRootManager : DomainService, ITransientDependency, IUnitOfWorkEnabled, IScreenRootManager
    {
        private readonly IScreenDesignRepository _screenDesignRepository;
        private readonly IObjectMapper _mapper;
        private readonly ILogger<ScreenRootManager> _logger;
    
    
    
        public ScreenRootManager(IScreenDesignRepository screenDesignRepository, IObjectMapper mapper, IUnitOfWorkManager unitOfWorkManager, ILogger<ScreenRootManager> logger)
        {
            var screenDesignRepository1 = screenDesignRepository;
            _screenDesignRepository = screenDesignRepository;
            _mapper = mapper;
            _logger = logger;
        }
        public async Task<ScreenDesignCreateResult> CreateAsync(
          IScreenDesignCreateCommand screenDesignDto
      )
        {
    
                var screenDesign = new ScreenDesign(
                screenDesignDto.Type,
                screenDesignDto.ProgramName,
            Guid.NewGuid(),
               screenDesignDto.FieldId,
               screenDesignDto.FieldName,
              screenDesignDto.FieldDescription,
               screenDesignDto.GridJsonHeader,
               screenDesignDto.TabJsonHeader,
              screenDesignDto.PopupOrderAppearance,
    
               screenDesignDto.TabSequence,
    
               screenDesignDto.DontShow,
               screenDesignDto.IsMandatoryField,
               screenDesignDto.AllowMinusDataEntry,
               screenDesignDto.DontRefreshDataAfterRegistration,
               screenDesignDto.CanNotChangeFieldWithEdit,
               screenDesignDto.AllowFiltering,
               screenDesignDto.IsPrimary,
               screenDesignDto.Alignment,
               screenDesignDto.Format,
               screenDesignDto.Width,
               screenDesignDto.MessageKey,
               screenDesignDto.LookupUrl,
               screenDesignDto.IsGrid,
               screenDesignDto.HeaderUrl,
               screenDesignDto.DataSourceUrl,
               screenDesignDto.TabTitle,
               screenDesignDto.TemplateName,
               screenDesignDto.PropertyDataType,
               screenDesignDto.DisplayLocation,
               screenDesignDto.SubTab,
               screenDesignDto.SubTabSequence,
               screenDesignDto.DataLength,
               screenDesignDto.ColumnOrder,
               screenDesignDto.DefaultOrder,
               screenDesignDto.NotAllowChangesNotBlank,
              screenDesignDto.MinimumCharLength,
               screenDesignDto.MaximumCharLength,
               screenDesignDto.IsTree,
               screenDesignDto.RelationField,
               screenDesignDto.CascadeFrom,
               screenDesignDto.IsDMS,
               screenDesignDto.IsDMSEnum
            );
            try
            {
                var data = await _screenDesignRepository.InsertAsync(screenDesign);
                var returnDto = _mapper.Map<ScreenDesign, ScreenDesignCreateResult>(data);
    
                return returnDto ;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "error occured");
    
                throw;
            }
        }
    
    
    }
    
     public class CreateScreenDesignConsumer : IConsumer<IScreenDesignCreateCommand>
     {
         private readonly ScreenRootManager _screenRootManager;
         private readonly ILogger<CreateScreenDesignConsumer> _logger;
    
         public CreateScreenDesignConsumer(ScreenRootManager screenRootManager, ILogger<CreateScreenDesignConsumer> logger)
         {
             _screenRootManager = screenRootManager;
             _logger = logger;
         }
         
      //I changed to virtual here
         public virtual async Task Consume(ConsumeContext<IScreenDesignCreateCommand> context)
         {
    
             try
             {
                 var result = await _screenRootManager.CreateAsync(context.Message);
                 await context.RespondAsync(new Result<ScreenDesignCreateResult>(data: result));
             }
             catch (Exception ex)
             {
                 await context.RespondAsync<Fault<Result>>
               (new { Message = "ScreenDeisgn:CreateFail", FaultMessage = ex.Message, FaultStackTrace = ex.StackTrace });
    
             }
         }
     }
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi

    Inject IScreenRootManager here

  • User Avatar
    0
    Teknosol created

    I tried that too but the error persists.

    public class CreateScreenDesignConsumer : IConsumer<IScreenDesignCreateCommand>
    {
    
    //changed interface
        private readonly IScreenRootManager _screenRootManager;
        private readonly ILogger<CreateScreenDesignConsumer> _logger;
    
        public CreateScreenDesignConsumer(IScreenRootManager screenRootManager, ILogger<CreateScreenDesignConsumer> logger)
        {
            _screenRootManager = screenRootManager;
            _logger = logger;
        }
    
        public virtual async Task Consume(ConsumeContext<IScreenDesignCreateCommand> context)
        {
    
            try
            {
                var result = await _screenRootManager.CreateAsync(context.Message);
                await context.RespondAsync(new Result<ScreenDesignCreateResult>(data: result));
            }
            catch (Exception ex)
            {
                await context.RespondAsync<Fault<Result>>
              (new { Message = "ScreenDeisgn:CreateFail", FaultMessage = ex.Message, FaultStackTrace = ex.StackTrace });
    
            }
        }
    }
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    I can't build the project you shared.

  • User Avatar
    0
    Teknosol created

    It works for us too, I can show it with zoom if you want. my mail : ali.ozen@teknosol.com.tr

  • User Avatar
    0
    Teknosol created

    Hi, Can you schedule a meeting today at 10:00 GMT+3 or according to your availability? I saw it late in your yesterday's email.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi

    https://us05web.zoom.us/j/5929668302?pwd=UXl2M2RUeG5PazVSY2ZCOW1NMUxtZz09

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    The problem is you haven't configured the ABP module.

    I shared the project with you, please check it.

  • User Avatar
    0
    Teknosol created

    Thank you very much for your support, the project is working,

    Now we have another question: what solution should we implement to transfer tenant and userid information to the worker service via masstransit ? How can we add abp authorization control?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Please create a new question, thanks.

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