使用 asp.net 身份RTW版本。
我需要在事务中执行多个操作,包括UserMananger
函数调用和对DbContext
的其他操作(例如:创建新用户,将其添加到组并执行一些业务逻辑操作)。
我应该怎么做?
我的想法随之而来。
事务范围
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
// Do what I need
if (everythingIsOk) scope.Complete();
}
问题是:UserManager
函数都是异步的,TransactionScope
不是为与 async/await 一起工作而设计的。它似乎在.Net Framework 4.5.1中解决了。但是我使用 Azure 网站来托管我的项目生成,因此我还不能以 4.5.1 为目标。
数据库事务
public class SomeController : Controller
{
private MyDbContext DbContext { get; set; }
private UserManager<User> UserManager { get; set; }
public AccountController()
{
DbContext = new MyDbContext()
var userStore = new UserStore<IdentityUser>(DbContext);
UserManager = new UserManager<IdentityUser>(userStore);
}
public async ActionResult SomeAction()
{
// UserManager uses the same db context, so they can share db transaction
using (var tran = DbContext.Database.BeginTransaction())
{
try
{
// Do what I need
if (everythingIsOk)
tran.Commit();
else
{
tran.Rollback();
}
}
catch (Exception)
{
tran.Rollback();
}
}
}
}
这似乎有效,但是我如何对其进行单元测试?
UserManager<>
构造函数接受IUserStore<>
,所以我可以很容易地存根它。
UserStore<>
构造函数接受DbContext
,不知道我怎么能存根这个。
您可以实现自己的测试用户存储,该用户存储可以为单元测试存根。
如果要在测试中使用实际的 EF 用户存储,这也将起作用,但默认情况下它将使用 DefaultConnection 字符串创建数据库。 如果要确保每个测试的数据库干净,则可以指定数据库初始值设定项以始终在测试中删除/重新创建表。