Bra*_*don 5 c# database asp.net concurrency sqlmembershipprovider
您将如何使用以下代码解决并发问题?在此示例中,我们想知道用户验证失败的原因.问题是这段代码对数据库进行了两次单独的调用,但我们希望整个方法在概念事务中发生.具体来说,我们对隔离感兴趣.在确定身份验证失败的原因之前,我们不希望在执行此方法期间并发写入会影响我们的读取.
我想到了一些解决方案:Thread Locking,TransactionScope和Optimistic Locking.我非常喜欢乐观锁定的想法,因为我认为冲突可能很少见,但是.NET没有内置任何东西,对吧?
此外 - 在这种情况下,这真的是值得关注的吗?什么时候这样的并发问题很重要,什么时候不重要?在实施解决方案时需要考虑什么?性能?锁的持续时间?冲突发生的可能性有多大?
编辑:在回顾Aristos的回答之后,我认为我真正追求的是Authenticate方法的某种" 快照 "隔离级别.
public MembershipStatus Authenticate(string username, string password)
{
MembershipUser user = Membership.GetUser(username);
if (user == null)
{
// user did not exist as of Membership.GetUser
return MembershipStatus.InvalidUsername;
}
if (user.IsLockedOut)
{
// user was locked out as of Membership.GetUser
return MembershipStatus.AccountLockedOut;
}
if (Membership.ValidateUser(username, password))
{
// user was valid as of Membership.ValidateUser
return MembershipStatus.Valid;
}
// user was not valid as of Membership.ValidateUser BUT we don't really
// know why because we don't have ISOLATION. The user's status may have changed
// between the call to Membership.GetUser and Membership.ValidateUser.
return MembershipStatus.InvalidPassword;
}
Run Code Online (Sandbox Code Playgroud)
根据我在这里和这里的阅读,似乎System.Transactions.TransactionScope
包装整个方法应该自动将数据库调用纳入公共事务中,从而在整个事务范围内实现事务安全。
你想做这样的事情:
public MembershipStatus Authenticate(string username, string password)
{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot }))
{
MembershipUser user = Membership.GetUser(username);
if (user == null)
{
// user did not exist as of Membership.GetUser
return MembershipStatus.InvalidUsername;
}
if (user.IsLockedOut)
{
// user was locked out as of Membership.GetUser
return MembershipStatus.AccountLockedOut;
}
if (Membership.ValidateUser(username, password))
{
// user was valid as of Membership.ValidateUser
return MembershipStatus.Valid;
}
// user was not valid as of Membership.ValidateUser BUT we don't really
// know why because we don't have ISOLATION. The user's status may have changed
// between the call to Membership.GetUser and Membership.ValidateUser.
return MembershipStatus.InvalidPassword;
}
}
Run Code Online (Sandbox Code Playgroud)