Stop users overwriting each other - c#

I'm wanting to stop two users accidently overwriting each other when updating a record. That is to say two users load a page with record A on it. User one updates record to AB and user two updates it to AC.
I don't just want the last to hit the database to override. I need a mechanism to say the record has been updated so yours can't be saved.
Now the two ideas I have is to time stamp the records and check that. If it doesn't match up don't allow the update. The second method is to GUID the record each time an update is performed, check the GUID and if it doesn't match don't update.
Are either of these methods valid, if so, which is best. If not, what do you suggest. This is in C# if it makes a difference
Thanks

The two methods you've mentioned are effectively equivalent - either way you've got a unique identifier for "the record at the checkout time" effectively. I don't have any particular view on which is better, although a timestamp obviously gives you the added benefit of data about when the record was valid.
An alternative is to remember what the previous values were, and only allow an update if they match - that way if user A started editing a record, then user B goes in and changes something, then changes it back, user A's edits are still valid.
The term for these techniques is optimistic locking (or optimistic concurrency control).

There is actually a third method. To do the update, issue an update statement of this form:
UPDATE table SET update_field = new_value
WHERE db_pk = my_pk // assume primary key immutable
AND update_field = original_field_value
where original_field_value is the value of the field before the update was attempted. This update will fail if someone else has modified update_field, unless they have changed it to the same value that you have.

You're describing Optimistic Locking, a valid and useful technique.
See references here.

Either method is valid for checking.
As to which is the best you have to look at the size of your app and how long it will take to implement each one. So if this is only ever going to happen occasionally then I'd prob go for the quicker solution and implement the timestamp option.
If you want something more detailed google concurrency - heres an article to start with - concirrency

I am using the first option. Update the timestamp on each update. So at the time of update we check the equality of the timestamp.

Do the terms optimistic and pessimistic locking ring a bell. These are the two recognised approaches to the problem you are describing. It sounds like you are working in a web environment. In this case the former option (optimistic locking) is more appropriate. You have gone on to describe how this would generally be implemented. It is common to use a timestamp or a version number to check if the record has been updated since the record was retrieved. One other thing to consider is to let your users know that there has been a change to the underlying data and potentially give them the option to choose between what they have attempted to save and what was save by another user. This choice really depends on what the business rules are.

Related

Handle concurrency in the user interface when a data record is deleted/updated

I would like to know how should I handle the scenarios in the user interface when:
1.) A user deletes a data record which got already deleted by another user
When the data record is already deleted it won`t be deleted anymore and with something like "Delete From Table Where Id = #IdToDelete" nothing bad should happen.
But should I not tell my user instead:"Sorry we could not delete the data record because it got already deleted by user xyz" ??
2.) A user updates a data record which got already modified by another user?
Should I show for all my update() scenarios a window to the user with the new value and old value and let him choose or decide finally what will win ?
1) Generally, I wouldn't expect any message to be displayed to the user here since functionally what they asked to be done was done.
2) This is where you often get a warning about trying to update a modified record displayed to the user. How you display that warning depends a lot on your user requirements and how complicated a warning you want to display. The simplest solution is to warn them and ask them to refresh their local copy of the record, but this usually means that they need to re-do their changes which is a frustration point for users. Showing them the conflicts would be a nicer user experience, but could be a bit more complicated especially for large records.
1) Where does the information would come from? If you don't log who deleted what record then the database would not tell you this information.
2) It depends on your app - there are cases where "the last wins" strategy is OK and there are cases when it is not OK. You decide what you need/want to do if there are conflicts

Will having a pseudo-incremental number for bug ID be a problem?

Note that when I say "client", I mean businesses or organizations that have signed up for the service.
I am creating a bug tracking application. I have decided to go with multi-tenant approach with respect to both the application instance and the database.
Hence, there is one huge bugs table with entries from all clients. The bug ID is an identity specification. Because of this, when any user under any client adds a bug, it gets incremented. For a client who has added just 3 tasks, the task IDs could be #45, #49, #53 because users from other clients may have added some in between!
Is this acceptable from a use-case point of view?
Sometimes clients may take the latest bug ID to be a rough measure of the number of bugs. But in fact it will be the TOTAL bugs in the system. Or they will be plain surprised if their first bug starts from #51134!
On the other hand, if I have this particular ID "behind the scenes", and calculate a "visible" ID for each client separately, they will see the numbers in order. But, when passing a reference bug ID as parameters in URLs I cannot use the user-visible ID because it is not unique. I don't think a ClientID - BugID combo will be elegant. I am afraid using the original identity specification value will cause confusion because the user will see one ID in the UI and another ID in the URL. And no need to say developers will try to use the URL by altering the ID and watch it fail.
How can I solve this issue? I do not want to go to a multi-database approach as I am kind of scared of the maintenance and upgrade process.
I think the principle of least surprise applies here: you need to be consistent with whatever you do. If you are unable to modify the URL scheme then that just leaves non-sequential ID's as the only viable solution. I don't personally see an issue with this, most bug trackers will be able to generate reports of how many bugs were reported in a given period, or how many on a specific project, etc.
On a slightly unrelated note, at work we use a single bug tracking system for all our projects. The system as a whole has a single incrementing ID for bugs in any project. We've never had an issue.
As a general rule of thumb don't show your surrogate keys (IDENTITY values) to your users if you can at all help it. Humans eventually want to change something that they know about so they need not know the primary key values...
The idea about generating a human-consumable identifier would solve your problem best, as you mention, just don't use it like a key in your system. Use your surrogate keys as the keys. (There are usually ways around passing keys in the url string...) Rather, treat your human consumable key as a display field after its initial generation.
Consider concatenating client name abbreviation or client company abbreviation or a portion of the date/time or other counter that you determine with a separate query against context (SELECT MAX(?) FROM q) or a combination these...
Good luck!
One special case I wanted to mention: if this is a public facing website, i.e. public support page or similar, where the customer gives you the support ticket number by phone (i.e. break of the communication medium) then it would be wise to construct an "intelligent" id. For example 5 numbers + checksum. Then the operator (or the system) can more easily check for misread ticket numbers.

detect duplicate insert

Is there an easier way to prevent a duplicate insert after refresh? The way I do it now is to select everything with the all fields except ID as parameters; if a record exists i don't insert. Is there a way to possible detect refresh?
Assuming it's a database, you could put a unique constraint on the combination of "all fields except ID" and catch the exception on an insert or update.
I agree with #Austin Salonen that you should start by protecting the DB with primary keys, unique constraints and foreign keys.
That done, many websites will include some JS behind submit buttons to disable the button immediately before sending on the request. This way, users who double click don't send two requests.
I think you may want to the EXISTS function.
Here's a simple explanation of EXISTS I found through google.
Like Dereleased said, use a 303-based redirect. Make the form submission use POST and then after saving have it send a 303 header and send them to the post-submit URL via a Location header which will be fetched via GET and a refresh will not be re-posting data.
It has been a long time since I have done any real web work. But back in the 1.1 days I remember using ids associated with a postback to determine if a refresh had occured.
After a quick search I think this is the article I based my solution from:
http://msdn.microsoft.com/en-us/library/ms379557(VS.80).aspx
It basically shows you how to build a new page class that you can inherit from. The base class will expose a method that you call when you are doing something that shouldn't be repeated on a refresh, and an IsPageRefresh method to track if a refresh has occured.
That article was the basis for alot of variations with similar goals, so it should be a good place to start. Unfortunately I can't remember enough about how it went to really give any more help.
I second the option to redirect a user to another (confirmation) page after the request has been submitted (a record inserted into the database). That way they will not be able to do a refresh.
You could also have a flag that indicates whether the insert request has been submitted and store it either on the page (with javascript) or in the session. You could also go further and store it somewhere else but that's an architectural decision on the part of your web application.
If you're using an AJAX request to insert a record then it's a bit harder to prevent this on the client side.
I'd rather do an indicator/flag then compare the fields. This, of course, depends on your records. For example, if it is a simple shop and the user wants to make an identical order then you will treat it as a duplicate order and effectively prevent the functionality.
What DB are you using? If it's MySQL, and certain other factors of your implementation align, you could always use INSERT IGNORE INTO .... EDIT: Struck for SQL Server
Alternatively, you could create "handler" pages, e.g. your process looks like this:
User attempts to perform "action"
User is sent to "doAction.xxx"
"doAction.xxx" completes, and redirects to "actionDone.xxx"
???
Profit!
EDIT: After re-reading your question, I'm going to lean more towards the second solution; by creating an intermediate page with a redirect (usually an HTTP/1.1 303 See Other) you can usually prevent this kind of confusion. Checking uniques on the database is always a good idea, but for the simple case of not wanting a refresh to repeat the last action, this is an elegant and well-established solution.

Is there any library/framework for undo/redo changes of rows in database?

May be my title is not clear. I am looking for some kind of version control on database tables, like subversion does on files, like wiki does.
I want to trace the changes log.
I want to extract and run the diff in reverse. (undo like a "svn merge -r 101:100").
I may need a indexed search on the history.
I've read the "Design Pattern for Undo Engine", but it is related to "Patterns". Are there anything I could reuse without reinvent the wheel?
EDIT:
For example, bank account transactions. I have column "balance"(and others) updated in table. a user will find a mistake by him 10 days later, and he will want to cancel/rollback the specific transaction, without changing others.
How can I do it gracefully in the application level?
Martin Fowler covers the topic in Patterns for things that change with time. Still patterns and not an actual framework but he shows example data and how to use it.
You could use a revision approach for each record that you want to trace. This would involve retaining a row in your table for every revision of a record. The records would be tied together by a shared 'ID' and could be queried on the 'Revision Status' (e.g. Get the latest "Approved" record).
In your application tier, you can handle these records individually and roll back to an earlier state if needed, as long as you record all the necessary information.
[ID] [Revision Date] [Revision Status] [Modified By] [Balance]
1 1-1-2008 Expired User1 $100
1 1-2-2008 Expired User2 $200
2 1-2-2008 Approved User3 $300
1 1-3-2008 Approved User1 $250
Pedantic point. Your bank account example would not get past an auditor/regulator.
Any erroneous entries in an account should be left there for the record. An equal and opposite correction transaction would be applied to the account. In effect rolling back the original transaction but leaving a very obvious trace of the original error and its correction.
I'd go with a bi-temporal database design, which would give you all the data required to perform and rollback, whether that means inserting more rows or simply deleting the later modifications.
There's a fair amount of subtlety to such a database design but there's are very good book on the subject:
Developing Time-oriented Database Applications in SQL by Richard T. Snodgrass
available for download here:
http://www.cs.arizona.edu/people/rts/tdbbook.pdf
Using a database transaction would be a bad idea because the locks it would create in the database - basically database transactions should be as short as possible.
Anything in the application layer, unless it has some persistence mechanism itself, won't survive application restarts (although that might not be a requirement).
Based on your comment to James Anderson, I would have the user interface write a new insert when cancelling a transaction. It would insert a new record into the table that had the same values as the cancelled transaction except the value would be a negative number instead of a positive number. If you have a structure that includes something to define the purpose of the transaction, I would make it say cancelled and the record number of the transaction it was cancelling.
Based on the various comments a possible solution for your problem would be to make a "date effective" table.
Basicly you add valid-from-date and valid-to-date columns to every table.
The "current" record should always have a valid_to_date of "2999-12-31" or some arbiteraly high value.
When a value changes you change the "valid-to-date" to the current date and insert a
new row with a valid-from-date of today and a valid-to-date of "2999-12-31" copy all the columns from the old row if they have not been changed.
You can create views with
"select all-columns-except-valid-xx-date from table where valid-to-date = '2999-12-31'"
Which will allow all your current queries to work unchanged.
This is a very common tecnique in data warehouse environments and for thing like exchange rates where the effective date is important.
The undo logic should be obvious.
I'm not aware of a specific pattern, although I have set up full undo/audit histories before using triggers and rowversions.
There are a couple of apps for MS Sql that let you trawl through the logs and see the actual changes.
I've used one called Log Navigator back with MS SQL 2000 that used to let me undo a specific historical transaction - I can't find it now though.
http://www.lumigent.com and http://www.apexsql.com do tools for viewing the logs, but I don't think either lets you roll them back.
I think the best way to do this is to write your application with this in mind - which you have a couple of good suggestions here already on how to do.

How to save objects when approval is needed to actually make changes?

So I have an object graph, let's just say it's an order. You have the order class, line item class, tracking number class, payment class. You get the idea.
Now the business requirement is any user can change the order, but order changes must be approved by the manager. Until the manger approves nothing changes. Managers can change anything, at any time, without approval.
What are the best practices for dealing with situations like this? Saving the many (possible) different states of the order object and eventually approving or rejecting the changes.
i'm using C# and Nhibernate.
Thanks, Kyle.
I would create a transaction table. It would have a record for each pending change. It would reference the order table.
So an order would get created but have a pending change; a record would be inserted into the orders table, with a status column of pending, and a record would be insterted into the OrderTransaction table.
For every change another record would get inserted into the OrderTransaction table.
I would also set up a RequestedChanges table with all the possible requested changes.
Similar to Sam WIlliamson's idea about a transaction table, I would use a temporary table.
Changes made by someone who is not a manager, go to new Order objects in the temp table. The manager will have an interface to review these orders pending approval, and the system will have all the changes saved already, but outside of the standard position.
This might be an issue for the user's interface as well, they will have to see both the official version of an order and the pending-revision version side by side to make sense of the state of the object.
Anyway I think your best bet is to store the objects as normal, but in a separate table from the official records, pending review by the manager. This temp table should never grow very large, as it represents the backlog of approvals the manager has to get to.
I do not have any experience with nHibernate.
For a scenario like this, it is better left to database to store Order (state = ForManagerToApproveOrReject) and it can then be queried to see which Orders are waiting for approval/rejection (from manager's view)
A manager can then either approve/reject it.
The inheritance mode of saving Order (ApprovedOrder, RejectedOrder) seems little odd.
a simple solution is to just make another order that is a copy of the original with the changes applied, the status set to PendingApproval, and an auto-increment VersionNumber. change the table's primary key to include ApprovalDate. Then the current, approved order is always the one with the most recent approval date.
If orders are not complete until approved you may want to have a pending orders, and completed orders table structure. Pending orders might just be serialized objects and only write it out to order, order lines etc once approved.
If you allow changing orders after approval it become more complicated, you may also need to take into account post approval steps, payment received, picking, packing, shipping etc.
There are lots of ways to do this type of thing, how you do it will really depend on what the real business requirements are. i.e. you say managers can change orders at any time, but should they really be allowed to change a shipped order?
I understand that part, the issue I'm having is figuring out how/where to save all the changes while the order is not approved. For instance, User A adds a payment, user B changes the address and User C adds a new line item.
until the manager approves the order stays as it was originally created (or retrieved from DB). Once manager is in the approval screen he/she can approve/reject each change. Changes are written to the original order and an audit is kept. User A changed xxx at yyy approved by zzz at aaa.
What you are describing is a workflow, it actually sounds to me like a good candidate for Windows Workflow Foundation. If your workflow is business critical I would be inclined to separate it out from your database logic, WWF will allow you to do this.
thanks for all the answers. The actual business use case is not creating orders, but if I tried to explain the actual business I'd have to write a couple paragraphs. The bottom line is managers need to moderate changes on a deeply nested object graph, before they "go live."
I like the transaction table idea.
I also like saving two versions of the "order," one with changes, one without.
I guess I'll have to dive into both and see what happens.

Categories

Resources