我正在使用通过域驱动设计体系结构开发的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
创建的那些记录。它不会还原ApplicationUser
(Role
和_appDbContext
创建的userManager
和RoleManager
内容。因此,我再次更新了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}}函数都可以正常工作,并且数据正在还原,但我不会继续进行。
所以,总结一下:
如果我使用
_appdbContext
为了解决问题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
我该如何解决?