【问题标题】:How to prevent UnitOfWork from saving changes in ASP.NET Boilerplate如何防止 UnitOfWork 在 ASP.NET 样板中保存更改
【发布时间】:2017-09-07 08:47:50
【问题描述】:

我有一个 get 方法,在该方法中我对要返回的对象的一些数组属性进行一些过滤:

    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>();
    }

例如属性WorkflowStepActions 需要被过滤掉以仅显示用户有权访问的操作,WorkflowStepConfigurations 也是如此。

问题在于UnitOfWork 模式。尽管这是一个GET 方法并且我不想保存任何数据,但在方法结束时,UnitOfWork 会将更改保存到数据库,删除当前调用中已过滤掉的WorkflowStepActions

我尝试使用 [UnitOfWork(IsDisabled=false)] 一起禁用 UnitOfWork,但随后我收到一条错误消息,指出无法访问存储库,因为它已被释放。

有什么方法可以AcceptChanges 到 UnitOfWork,或者让它自动停止保存更改?

【问题讨论】:

  • 尝试 Configuration.UnitOfWork.Scope = TransactionScopeOption.Suppress;
  • 如果你想让你自己的实体的私有副本发生变异,穷人的解决方案可能是把AsNoTracking扔在那里。

标签: c# asp.net-core aspnetboilerplate


【解决方案1】:

在哪里使用此方法很重要(在 appservice、domainservice、自定义类等中)

假设您在域服务中使用它

你必须为方法添加 [UnitOfWork] 属性并使方法虚拟化。

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

        }

如果您想以异步方式手动保存更改。您可以在任何应用程序服务中使用以下代码。

 await CurrentUnitOfWork.SaveChangesAsync();

如果你想开始一个新的工作单元,你可以使用这个

//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();
    }
}

要获取更多信息,请阅读文档 -> https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work

【讨论】:

    【解决方案2】:

    尝试这种解决方法,但在这种情况下,GetCurrentWorkflowStep 应该是独立的,即不会被您的另一个代码隐式调用:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      相关资源
      最近更新 更多