使用并发DBContext事务时,EF内核中的超时已到期

时间:2019-02-08 10:55:13

标签: c# entity-framework .net-core entity-framework-core-2.1 tracker-enabled-dbcontext

我正在使用通过域驱动设计体系结构开发的ASP.NET Core 2.1 Web API项目。

我有两个数据库上下文,Asp.net Identity使用AppDbContext(用于像UserManager一样进行用户和角色管理),Sprint1DbContext用于其他表的事务。

在startup.cs中,我使用了:

  string constring =  Configuration.GetValue<string>("DBConnectionString");
      services.AddDbContext<ApplicationDbContext>(options =>
              options.UseSqlServer(constring));



  services.AddIdentity<ApplicationUser, ApplicationRole>()
         .AddEntityFrameworkStores<ApplicationDbContext>()
         .AddDefaultTokenProviders();

  services.AddDbContext<Sprint1DbContext>
    (options =>  options
    .UseLazyLoadingProxies()
  .UseSqlServer(constring
 // , sqlServerOptions => sqlServerOptions.CommandTimeout(120) this is not worked
  )

//_dbContext is Sprint1DbContext 
// _appDbContext is AppDbContext 

我在CustomActionFilterAttribute类中使用了以下几行:

public override void OnActionExecuting(ActionExecutingContext context)
    {

      _dbContext.Database.BeginTransaction();

    }  

public override void OnActionExecuted(ActionExecutedContext context)
{
 if (context.Exception == null)
      {
        _dbContext.Database.CommitTransaction();

      }
      else
      {

        _dbContext.Database.RollbackTransaction();

   }
}

在服务类中,我正在使用以下业务代码:

// Some code
// creating Bill of the customer
 await billToDataRepository.Add(billTo);
 // some code

// creating new customer’s data AspNetUser, Role, and it Account record
 ApplicationUser user = new ApplicationUser
      {
        Name = model.FName + " " + model.LName,
        UserName = model.Email,
        Email = model.Email,
        PhoneNumber=model.PrimaryPhone,
      };
      // creating AspNetuser
      IdentityResult result = await userManager.CreateAsync(user, Constants.PasswordDefault);

  // some code for assigning the role to a user

  var account = new Account
      {
        Id = Guid.NewGuid(),
        FName = model.FName,
        LName = model.LName,
        AccountType = EnumAccountType.Customer,
        AspNetUserId = user.Id,
      };
 await accountDataRepository.Add(account);

// other application business logic

上面的Add方法在DataRepository类中定义:

public class DataRepository<TEntity> : IDataRepository<TEntity>
         where TEntity :  DomainEntity
  {
  public async Task<TEntity> Add(TEntity entity)
    {

      if (entity == null)
        throw new ArgumentException("entity is null");

      return await Task.Run(() =>
      {
        try
        {
          Context.Set<TEntity>().Add(entity);
          Context.SaveChanges();
        }
        catch (Exception e)
        {
          throw;
        }
        return entity;
      });

}
}

如果其他应用程序业务逻辑中发生任何异常,那么我必须回滚所有内容。由于我仅使用_dbContext.Database.RollbackTransaction(),因此它仅回滚_dbContext创建的那些记录。它不会还原ApplicationUserRole_appDbContext创建的userManagerRoleManager内容。因此,我再次更新了CustomActionFilterAttribute类。

public override void OnActionExecuting(ActionExecutingContext context)
    {

      _dbContext.Database.BeginTransaction();
           _appdbContext.Database.BeginTransaction();

    }  

public override void OnActionExecuted(ActionExecutedContext context)
{
 if (context.Exception == null)
      {
        _dbContext.Database.CommitTransaction();
                _appdbContext.Database.CommitTransaction();

      }
      else
      {

        _dbContext.Database.RollbackTransaction();
                _appdbContext.Database.RollbackTransaction();

   }
}

在为BeginTransaction编写_appdbContext之后,当我执行相同的服务类代码时,在以下代码上出现超时错误:

 await accountDataRepository.Add(account);

Add方法正在调用Add类的DataRepository方法,这意味着在accountDataRepository.Add方法调用的以下行上发生异常:

Context.Set<TEntity>().Add(entity);
          Context.SaveChanges();
  

"errorDetail":"Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.\r\nThe statement has been terminated. ---> System.ComponentModel.Win32Exception: The wait operation timed out\r\n

尽管两个上下文(RollbackTransaction_dbContext的{​​{1}}函数都可以正常工作,并且数据正在还原,但我不会继续进行。

所以,总结一下:

问题1

如果我使用

_appdbContext

问题2

为了解决问题1,我使用:

_dbContext.Database.BeginTransaction();

_dbContext.Database.CommitTransaction();

 _dbContext.Database.RollbackTransaction();


await billToDataRepository.Add(billTo); //record created and rollback
// unable to rollback 
IdentityResult result = await userManager.CreateAsync(user, Constants.PasswordDefault);  //record created and but not rollback
await accountDataRepository.Add(account);   //record created and rollback

我该如何解决?

0 个答案:

没有答案