Activities of "alexander.nikonov"

Hi. The easiest way appeared to be just to decorate a whole custom AppService class with [UnitOfWork] attribute, because this custom service was not inherited from ApplicationService of ABP. So I did not need to manually create uow everywhere in the methods. Thank you.

Thank you, I will try and let you know.

Some more questions.

A) with my old approach (i.e. having BatchDbContext _dbContext DI in IApplicationService) I used the following approach to speed-up DB operations involving creating many records:

    _dbContext.ChangeTracker.AutoDetectChangesEnabled = false;
    (addedCount, addedLines) = await TryCreateChunkAsync(...); //inserting some data into DB by chunks - each chunk is created in a separate UnitOfWork
    _dbContext.ChangeTracker.AutoDetectChangesEnabled = true;
    

But now when I switch to IDbContextProvider<BatchDbContext> _dbContextProvider DI - what is the corresponding change here? Should I still accomplish this using var dbContext = await _dbContextProvider.GetDbContextAsync(); dbContext.ChangeTracker.AutoDetectChangesEnabled = ... or those ChangeTracker operations do not make sense anymore?

B) if I do not interact with DbContext directly, do I still need to make additional changes for my scenario in the following method?

    [NonAction]
    public virtual async Task&lt;...&gt; InsertAsync(...)
    {
        using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) //Adding Unit Of Work
        {
                var entity = _objectMapper.Map&lt;...&gt;(input);
                //Any additional changes related to using DbContext??
                var newEntity = await _entityRepository.InsertAsync(entity);
                await uow.CompleteAsync();
                return _objectMapper.Map&lt;...&gt;(newEntity);
        }
    }
    

C) Any modifications required for methods which do not change the data in DB (i.e. read methods)? What is important - I still want to be sure that such a method "sees" data which have been added by other Hangfire job by this moment.

And saying honestly, I do not know why the exception like mine ever happens. Indeed, the documentation which link you have provided, mentions that "Application service methods" are considered as a unit of work. Which means, that none of DB changes done by one app service should conflict with those of other app service, right? Maybe the reason is that all my app services in Hangfire server implement IApplicationService, but do not inherit from ApplicationService of ABP - so they are not considered as a Unit Of Work? This is done intentionally and I want to leave it like this. I've tried to implement IUnitOfWorkEnabled in all my services instead of doing the other changes you suggested, but then I got the exceptions (which need to be investigated, but probably it is not the way to go). I am confused with all possible approaches which are suggested. Could you please explain, if they are mutually exclusive or complementary?

Thank you. Whereas I cannot share actual code, I can show the way DbContext is used. So any Hangfire job can be scheduled at any time (they can interpose) and do any kind of CRUD operation:

    public class ContextAgnosticBatchAppService : IContextAgnosticBatchAppService
    {
        private readonly BatchDbContext _dbContext;
        private readonly IBatchRepository _batchRepository;
        ...
    
        public ContextAgnosticBatchAppService
        (
            BatchDbContext dbContext,
            IBatchRepository batchRepository,
            ...
        )
        {
            _dbContext = dbContext;
            _batchRepository = batchRepository;
            ...
        }
        
        [NonAction]
        public virtual async Task&lt;...&gt; AddForServerAsync(...)
        {
            var data = await _batchRepository.InsertAsync(...);
            ...        
            return ...;
        }
    
        [NonAction]
        public virtual async Task&lt;...&gt; UpdateForServerAsync(...)
        {
            await _dbContext.Batches.Where(...)
                .ExecuteUpdateAsync
                (
                    x => x.SetProperty(...)
                );
    
            return ...;
        }
    	...
    }
    

Repositories use DbContext in the following way:

var dbContext = await GetDbContextAsync();

All Hangfire jobs work with the same database, so even though each job is supposed to work with its own tenant - any possible database data collisions need to be avoided, but at the same time it is desirable that any job was aware about the changes already done by other job (e.g. added entities).

Hi. Sorry, I am not sure I understand. I use AddAbpDbContext extension as in the rest of the projects, because Hangfire server jobs consume our custom repositories DI which are based on the relevant AbpDbContext:

    public class SomeBatchRepository : EfCoreRepository&lt;BatchDbContext&gt;, IRepository&lt;...&gt; ...
    public class SomeOtherRepository : EfCoreRepository&lt;InternalCoreDbContext&gt;, IRepository&lt;...&gt; ...
    
    public class InternalCoreDbContext : AbpDbContext&lt;InternalCoreDbContext&gt; ...
    public class BatchDbContext: AbpDbContext&lt;BatchDbContext&gt; ...
    

And what do you mean specifically under "EF COreDbContext"?

  • ABP Framework version: v8.1.3
  • UI Type: Angular
  • Database System: EF Core (Oracle)
  • Auth Server Separated OpenID Server

We utilize a Hangfire server. So far its module has used a standard EF setup suggested by ABP framework:

public class BatchEntityFrameworkCoreModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddAbpDbContext&lt;BatchDbContext&gt;(options =>
        {
            ...
        });

        context.Services.AddAbpDbContext&lt;InternalCoreDbContext&gt;(options =>
        {
            ...
        });

        Configure&lt;AbpDbContextOptions&gt;(options =>
        {
            options.PreConfigure(abpDbContextConfigurationContext =>
            {
                abpDbContextConfigurationContext.DbContextOptions.UseLoggerFactory(LoggerFactory.Create(loggingBuilder => loggingBuilder.AddConsole()));                    
                abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging();
            });
           
            options.UseOracle(options => options.MaxBatchSize(100));
            options.UseMultiDb(context.Services.GetConfiguration());
        });

        context.Services.AddTransient&lt;IAuditPropertySetter, Abp.DataExtensions.Entities.LogAuditPropertySetter&gt;();        
        AbxEfSettingProvider.Initialize(context.Services.GetConfiguration());
    }
}

However when we run two time-consuming jobs on this server, the second job raises the exception, if the first job is still in progress:

An attempt was made to use the context instance while it is being configured. A DbContext instance cannot be used inside 'OnConfiguring' since it is still being configured at this point. This can happen if a second operation is started on this context instance before a previous operation completed. Any instance members are not guaranteed to be thread safe.

I have found the solution where a user switches from DbContext to DbContextFactory using the setup:

builder.Services.AddDbContextFactory&lt;PowerBlazorDbContext&gt;(opt => opt.UseSqlServer(builder.Configuration.GetConnectionString("PowerBlazorDb")));    

And then uses the following DI:

public class PowerService : IPowerService
{
    private readonly IDbContextFactory&lt;PowerBlazorDbContext&gt; _contextFactory;
    public PowerService(IDbContextFactory&lt;PowerBlazorDbContext&gt; contextFactory)
    {
        _contextFactory = contextFactory;
    }

    //Accessing the DbContext
    public async Task&lt;...&gt; SomethingAsync(...)
    {
        await using var _context = await _contextFactory.CreateDbContextAsync();
        ...
    }
}

How should we properly switch from AddAbpDbContext to AddDbContextFactory? Or you may have other solutions?

@sumeyye.kurtulus thank you for the reply. Whereas I cannot handle this issue now and I did not dig into the suggested project, I have a quick question for you: will it be easy to integrate the authenticate service solution by your link into our ABP-based solution? In fact, I have no idea how it works "under the hood" now, because we just use a standard AuthService from @abp/ng.core to log out and it is place in a separate NPM component. No custom logic attached. So what is it supposed to be at the very end? Replacing AuthService of ABP with the customized version from the mentioned project via providers?

Reopening. Thank you for your response. Unfortunately, I am currently overwhelmed with my existing tasks and do not have the time to analyze your reply at the moment.

Any update?

The issue is resolved - the cleanup process is now successful. Thanks again.

You have a point here, thank you - some of the projects were missing AbpOpenIddictEntityFrameworkCoreModule dependency in their EntityFrameworkCoreModule. Nevertheless, I am planning to leave the site running overnight and will check the log in the morning.

Showing 1 to 10 of 340 entries
Made with ❤️ on ABP v9.1.0-preview. Updated on December 13, 2024, 06:09