Concurrency problems with multiple independent database transactions?

How do you solve the concurrency problem with the following code? In this example, we would like to know why the user did not authenticate. The problem is that this code makes two separate calls to the database, but we would like the whole method to be executed inside a conceptual transaction. In particular, we are interested in isolation . We do not want concurrent writes during the execution of this method to affect our readings before we determine the cause of the authentication failure.

Several solutions come to mind: Thread Lock , TransactionScope, and Optimistic Lock . I really like the idea of ​​Optimistic Locking, since I think conflicts are likely to be rare, but there is nothing in .NET to do this, right?

Also - is something REALLY bothering in this case? When concurrency problems like this are important to consider, and when not? What should be considered when implementing a solution? Performance? Lock duration? How likely are conflicts?

Change: . After considering Aristos' answer, I think I'm really in some way a snapshot for the Authenticate method.

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 status may have changed
        // between the call to Membership.GetUser and Membership.ValidateUser.
        return MembershipStatus.InvalidPassword;
    }
+5
source
2

, , 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 status may have changed
        // between the call to Membership.GetUser and Membership.ValidateUser.
        return MembershipStatus.InvalidPassword;
    }
}
+1

mutex, , . , -.

public MembershipStatus AuthenticateLock(string username, string password)
{
    if(string.IsNullOrEmpty(username))
      return MembershipStatus.InvalidUsername;

    // TODO: Here you must check and clear for non valid characters on mutex name
    using (var mutex = new Mutex (false, username))
    {
         // possible lock and wait, more than 16 seconds and the user can go...
         mutex.WaitOne (TimeSpan.FromSeconds(16), false);

         // here I call your function anyway ! and what ever done...
         //  at least I get a result
         return Authenticate(username, password)
    }
}

: Membership.ValidateUser Membership.GetUser .

asp.net , , , , , . . , .

: ASP.Net

jQuery Ajax -

+1

All Articles