Open Closed

Not always saving data #838


0
RonaldR created

Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.

  • ABP Framework version: v4.1.2
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Seperated (Angular): yes
  • Exception message and stack trace:
  • Steps to reproduce the issue:
  • So the problem we are habing is we are invoking jobs through hangfire. i am assuming this problem exists everywhere but i know how to recreate it here.
  • In the function we do a lot of database work. we create a job with an id, then give that id to every record processed, then when we are done we update the dtatus of the job.
  • if there is an exception we log it and report the job failed.
  • what we have found is that if it hits the exception, no data is saved. this is partially the expected behavior.
  • When the function to create the job orlog an exception is called, we use an irepositoy, and we call save changes in those functions so that data should be saved.
  • we do not call the save changes at the end of our look unless it is successful.
  • what we find though is if it fails and we do not save changes in the main function and we exit out, none of the data saves, including the job, which we did call save changes after
  • we are not identifying this as unitofwork, andi looked at the backgroundjob interface and did not see execute as unitof work.
  • why would we be getting htis behavior? should anything done prior to the save changes be saved?

4 Answer(s)
  • 0
    RonaldR created
    public async Task LinuxNetstatsDiscovery(string TaskName, Guid? TenantId)
    {
    
    	DateTime nowDt = DateTime.UtcNow;
    	List<string> failedIpAddesses = new List<string>();
    
    	using (CurrentTenant.Change(TenantId))
    	{
    		var sourceOfTruthNewDevices = new List<SourceOfTruthDataModel>();
    **This class function is defined below	**	
    		Guid BgjID = await _helperRepository.CreateBackgroundJobProcessingRecord(TenantId, $"{OperatingSystemEnum.Names.Linux} {DiscoveryType} Discovery");
    		List<HostListItemModel> hosts = await _helperRepository.GetHostList(TenantId, OperatingSystemEnum.OperatingSystem.Linux);
    
    		try
    		{
    			foreach (var host in hosts)
    			{
    				... do our processing ...
    				add record to DbContenxt.MyTable(record);
    			}
    
    			await _helperRepository.UpdateBackgroundJobStatusSuccess(BgjID, failedIpAddesses);
    			await DbContext.SaveChangesAsync();
    		}
    		catch (Exception ex)
    		{
    			//DbContext.Reset();
    			LogException(ex);
    			await _helperRepository.UpdateBackgroundJobStatusError(BgjID, failedIpAddesses);
    			throw;
    		}
    	}
    }
    
    
    public async Task<Guid> CreateBackgroundJobProcessingRecord(Guid? tenantId, string jobName)
    {
    	BackgroundJobDataModel jobDetails = new BackgroundJobDataModel(_guidGenerator.Create())
    	{
    		StartTime = DateTime.UtcNow,
    		TenantId = tenantId,
    		JobName = jobName,
    
    		Status = "Processing"
    	};
    
    	jobDetails.EndTime = jobDetails.StartTime;
    
    **_backgroundRepository is an IRepositry that is dependancy injected in the consturctor**
    	await _backgroundRepository.InsertAsync(jobDetails, true);
    	await _backgroundRepository.GetDbContext().SaveChangesAsync();
    
    	return jobDetails.Id;
    }
    

    so even though i save changes in this function, it does not unless i hit the save changes at the bottom of my loop

  • 0
    albert created
    Support Team

    it sounds like you need a seperate UnitOfWork scope.

    can you create a new UnitOfWork scope to save your changes. (you don't need to manually call the SaveChanges)

    https://docs.abp.io/en/abp/latest/Unit-Of-Work#begin-a-new-unit-of-work

  • 0
    RonaldR created

    I suspected it had to do with unit of work, but we arent tagging these functions as [UnitOfWork]. it is implicit in v4?

    so in the functions i want to make sure are outside the scope of their clling fucntions i need to wrap them in their own unit of work?

    thanks

  • 0
    albert created
    Support Team

    there's this rule; if your appservice / domain service method has seperate business logics which has to be handled seperately then you need to split them into different UOW scopes. Otherwise the complete request will be evaluated as transactional and will be rolled back if hits any exception.