Click here to Skip to main content
16,016,140 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
i'm writing a sales program and more than 1 user can use it.
what can i do when :
for example we have 3pen for sale in data base and
user1 want to sale 2 pen and in same time user2 want to sale 2 pen too !
what is you solution for this case ?
Posted
Comments
[no name] 1-Feb-15 11:53am    
This is not a problem, this is a very known scenario. And the solution is simply: The first who commit the transaction wins the race. Nothing more, nothing less.
itman2 1-Feb-15 12:02pm    
what does it men : The first who commit the transaction wins the race. ?
when the first one connect to database there is 3 pen and he can sale 2 of them and in same time the second user also connected and see 3 pen for sale and can sale 2 pen !

is it true ? what happend exactly in this case can you explain it ?

i cant andrestand it !
[no name] 1-Feb-15 12:21pm    
Basically you are right what they see. But again the first wins. If the second one commits the Transaction he should get a message like "sorry, items are not longer available".....

 
Share this answer
 
SQL Server won't solve this, but gives you the opportunity and the tools to react properly.
In general when you decrease the amount of the pens, you issue a single update statement. This is atomic, but can happen that the two users issue this update so that it is executed one right after the other. In that case If bpth are trying to buy those 2 you will end up with -2, which is bad.

Let me draft two approaches (the amount you want to reserve is 2 in both cases):
A) Optimistic approach a little bit modified
1) The client issues UPDATE store SET amount = amount - 2 WHERE product=123456 AND amount>2
2) ExecuteNonQuery returns the number of affected rows. If in that instant the amount is less than the desired value, the statement won't be effective because of the last condition. So it will return 0. You can react and notify the user.

B) Pre-lock
1) Wrap following statements in a READ COMMITTED transaction
2) Issue SET LOCK_TIMEOUT to set a short timeout
3) Issue an UPDATE store WITH (ROWLOCK) SET amount = amount WHERE product=123456 AND amount>2
4) Check the affected rows. If it is 0 than you don't have enough pens to sell, and you can ROLLBACK immediatelly, and alert the user. In this case, no row will be locked!
5) At this point any other user trying to update the same row using this approach will fail after the timeout specified before, as the row is locked.
5) Do other things.
6) Issue the regular UPDATE to decrease the amount.
7) COMMIT transaction
This second apporoach is interesting in real-world situations where the user is not buying a single item at once, but is preparing a complex order. Actually this approach is locking out the other user from that specific product. So you better not keep it locked for too long. In such a situation it is better to add an other field (let's call it reservation), and manipulate that field during this reservation process, instead of decreasing the actual amount. The amount is than decreased when the order is finished, or when it is actually shipped.
 
Share this answer
 
Comments
itman2 2-Feb-15 6:22am    
THANS MR zoltan zorgo

i think for this case i can lock my table ! because the time of update proces is less than 1 second .
can you say how can i lock my table
i write this code :


<pre lang="sql">Begin Transaction
Select * From TableName With(TabLockx)
commit transaction
</pre>

after run ths query my table locked and i canu unlock it again !

how can i lock my table an unlock it again ?
Zoltán Zörgő 2-Feb-15 7:03am    
Don't lock whole table, only the row, as I suggested. A transaction is holding the locks. So if you update the row without changing any actual data, you get the lock. Than after you commit or roll back, the lock is released. This is why you need to explicitly start the transaction.
A simple solution is to show the data consistently, if you're having 3 pens, then show 3. But let the first user who gets to order the 2 pens would get a chance to place the order, the second one if unluckily misses the opportunity by an instance of time, then show him the error message, or ask him to contact the shop owner for order etc. This is because, you can only provide 3 pens at maximum, the first one gets 2 and the second one can get (at maximum) only one pen. No matter what he does, or how ever he gets to click on the buy he cannot purchase 2 pens then. So you can just simply show him a message, saying, items are sold. There is no problem to be guilty for telling your clients that someone else bought the items he is looking for.

This is a very basic problem in database systems, where the users get to view the same data from the database but what do to when there are two members to order for same quantity and so on. The thing is, to make sure that your data is consistent, and every user is getting the live data from the database, once that has been taken care of, the only problem left is a delay in a few seconds before first user clicks for the order. Then you can show the second user an error message, saying, the items are sold. He will know that he is late.
 
Share this answer
 
Comments
itman2 1-Feb-15 15:34pm    
tanks
your solution means : sql server can fix problem ! is it right ?
i write this cod for sell_button and every thing must be ok . is it right ?

try
{

1- open connection
2- get amount of pen // amount=3
3- new_amount= sell_amount - old_amount //amount=2-3
4- update amount in database // amount= 1
}
catch
{
message : wrong amount...
}

with this cod when user1 and user2 in same time sell 2 pen , user1 can sell but user2 cant sell and the message show for him ! is it right ?



but this link say another thing : https://msdn.microsoft.com/en-us/library/aa0416cz%28v=vs.110%29.aspx[^]

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900