简体   繁体   中英

How to prevent UnitOfWork from saving changes in ASP.NET Boilerplate

I have a get method in which I do some filtering on some array properties of the object I want to return:

    public async Task<WorkflowStepDto> GetCurrentWorkflowStep(string entity, string status, string clientId = null)
    {
        var workflowStep = await _workflowStepRepository.GetAll().Include("WorkflowEntity")
                .Include("WorkflowStepActions").Include("WorkflowStepConfigurations")
                .FirstOrDefaultAsync(s => s.Name == status && s.WorkflowEntity.Name == entity);


       var workflowRoles = User.Claims.Where(c => c.Type == "workflowRole").Select(c => c.Value).ToArray();
       workflowStep.WorkflowStepActions =
                workflowStep.WorkflowStepActions
                    .Where(s => (workflowRoles.Contains(s.WorkflowRole) ||
                                 (workflowRoles.Length == 0 && string.IsNullOrEmpty(s.WorkflowRole)) ||
                                 s.WorkflowRole == "*")).OrderBy(a => a.Priority).ToList();
       workflowStep.WorkflowStepConfigurations = workflowStep.WorkflowStepConfigurations
                .Where(c => workflowRoles.Contains(c.WorkflowStepRoleId) ||
                            (workflowRoles.Length == 0 && string.IsNullOrEmpty(c.WorkflowStepRoleId)))
                .OrderBy(c => c.Priority).Take(1).ToList();

        return workflowStep.MapTo<WorkflowStepDto>();
    }

For example property WorkflowStepActions needs to be filtered out to show only the actions the user has access to, and the same goes for WorkflowStepConfigurations .

The problem is the UnitOfWork pattern. Even though this is a GET method and I don't want to save any data, at the end of the method the UnitOfWork saves the changes to the database, deleting the WorkflowStepActions that have been filtered out in the current call.

I tried disabling the UnitOfWork alltogether using [UnitOfWork(IsDisabled=false)] , but then I get an error saying that the repository cannot be accessed because it has been disposed.

Is there any way to AcceptChanges to a UnitOfWork, or to make it stop saving changes automatically?

It's important where you use this method (in appservice, domainservice, custom class etc..)

Assuming you use it in a domain service

You have to add [UnitOfWork] attribute to method and make method virtual.

        [UnitOfWork] 
        public virtual async Task<WorkflowStepDto> GetCurrentWorkflowStep(string entity, string status, string clientId = null)
        {

        }

And if you want to save changes manually in async way. You can use the code below in any application service.

 await CurrentUnitOfWork.SaveChangesAsync();

If you want to start a new unit of work, you can use this

//inject IUnitOfWorkManager to your class in constructor method.
private readonly IUnitOfWorkManager _unitOfWorkManager;


public async Task<WorkflowStepDto> GetCurrentWorkflowStep(...)
{
    using (var uow = _unitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
    {
        //You can save changes in any step of code to get some new inserted record's id... This is not required if you don't have such insertions.
        await _unitOfWorkManager.Current.SaveChangesAsync();

        //You have to apply Complete method in the end.
        await uow.CompleteAsync();
    }
}

To get further information read the docs -> https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work

Try this workaround, but at this case GetCurrentWorkflowStep should be standalone, ie not implicitly called by your another code:

public IUnitOfWorkManager _unitOfWorkManager {get; set;}

[UnitOfWork(IsDisabled = true)]
public async Task<WorkflowStepDto> GetCurrentWorkflowStep(...)
{
    using (var unitOfWork = _unitOfWorkManager.Begin())
    {
        //your code....
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM