如何在存储库中的异步方法中使用事务范围

时间:2016-05-07 03:30:35

标签: entity-framework model-view-controller

我的存储库有这个异步方法来更新两个表。这些表是不同的模式,因此有两个上下文。上下文是此存储库中的类变量。此方法是从Angap客户端应用程序调用的webapi调用的。我需要确保插入成功或两者都失败。尝试在任一上下文中插入重复记录失败后,无论是否传入非重复记录,服务器都将始终记住该记录。服务器将返回失败,直到托管服务器重新启动。有没有人知道如何在交易范围内处理这个问题?

public class RepositoryAsync: IRepositoryAsync {
  //CareMgmtTool schema context
  private CareMgmtToolContext cmtCtx = new CareMgmtToolContext();

  //App schema context
  private AppContext appCtx = new AppContext();

  //UserProfile schema
  private UserProfileContext userProfileCtx = new UserProfileContext();

  public async Task < int > PostUserFSR(int userId, int fsrId) {
    //poor man's transaction scope
    bool operation1Success, operation2Success = false;
    UserProfile_UserFacilityServiceRole vm1 = new UserProfile_UserFacilityServiceRole();
    vm1.UserId = userId;
    vm1.FacilityServiceRoleId = fsrId;
    UserProfile_UserFacilityServiceRole ufsr_UserProfileSchema = userProfileCtx
      .UserProfile_UserFacilityServiceRole.Add(vm1);
    operation1Success = true;

    App_SUserFacilityServiceRole vm2 = new App_SUserFacilityServiceRole();
    vm2.UserId = userId;
    vm2.FacilityServiceRoleId = fsrId;
    App_SUserFacilityServiceRole ufsr_appSchema = appCtx.App_SUserFacilityServiceRole.Add(vm2);
    operation2Success = true;

    if (operation1Success && operation2Success) {
      await userProfileCtx.SaveChangesAsync();
      await appCtx.SaveChangesAsync();
    }

    return ufsr_UserProfileSchema.UserFacilityServiceRoleId; //record key
  }

}

2 个答案:

答案 0 :(得分:0)

请在启用TransactionScopeAsyncFlowOption的情况下使用transactionScope包装逻辑。这里有很好的source作为参考。请参阅以下代码以获取一个想法(请注意,此代码尚未经过测试)。

 public async Task < int > PostUserFSR(int userId, int fsrId) 
    {
        using (var scope = 
            new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            try{
            UserProfile_UserFacilityServiceRole vm1 = new UserProfile_UserFacilityServiceRole();
            vm1.UserId = userId;
            vm1.FacilityServiceRoleId = fsrId;
            UserProfile_UserFacilityServiceRole ufsr_UserProfileSchema = userProfileCtx
              .UserProfile_UserFacilityServiceRole.Add(vm1);

            App_SUserFacilityServiceRole vm2 = new App_SUserFacilityServiceRole();
            vm2.UserId = userId;
            vm2.FacilityServiceRoleId = fsrId;
            App_SUserFacilityServiceRole ufsr_appSchema = appCtx.App_SUserFacilityServiceRole.Add(vm2);
              await userProfileCtx.SaveChangesAsync();
              await appCtx.SaveChangesAsync();
        scope.Complete();
            return ufsr_UserProfileSchema.UserFacilityServiceRoleId; //record key
              }
        }
        catche(Exception ex)
        {
            return 0;
         }
    }

谢谢你, 索马。

答案 1 :(得分:0)

我按照文档进行操作 https://msdn.microsoft.com/en-us/data/dn456843.aspx使用Transactions提供3个场景。在我的例子中,我只使用了在同一个上下文中开始事务的第一个场景。虽然所有三个场景的示例都使用SQL命令,但我只使用EF LINQ add()和remove()而不使用SQL命令和TransactionScope。以下引用文章&#34;总之,使用新的Database.BeginTransaction()和Database.UseTransaction()API,大多数用户不再需要TransactiionScope方法。&#34;