I have a forum application using asp.net, c#, sql server and linq to sql. It suffers from multiple inserts, I think when the insert button is pressed but also maybe when the browser is refreshed or back is clicked.
What's the most comprehensive way, or ways to prevent this.
UPDATE:
I currently use response.redirect after inserting text.
I think maybe the correct approach, upon reading the responses, is to disable the button immediately with javascript?
Followed by saving unique value on hidden field (or session?) on the form. Create a field in the db for this value and check this unique value against this field?
Thanks
Assign a UNIQUE cookie or hidden control to each page
Create a UNIQUE field in your table that holds this cookie or control value.
If a record is inserted with the same cookie, the INSERT will fail and you can process (or ignore) this condition.
When I've a page that does inserting or updating I typically do a Response.Redirect to another page after the update is completed, even if you just Response.Redirect to same page. That way if the page is refreshed you aren't re-posting your data.
Note that your problem isnt really specific to your database. You have a problem with multiple browser requests beeing sent, and you must get around that issue. Either use the redirect pattern as stated above by Dave or use Cookie signing
One example can be found here http://aspalliance.com/711_Preventing_Duplicate_Record_Insertion_on_Page_Refresh_or_Postback_of_a_Web_Form
use a primary key or unique constraint, if you can't do that I suggest you use the new MERGE statement which will insert if it doesn't exist or update if it does exists (don't know your business rules so that might not work in your situation) MERGE is SQL Server 2008 and up
Check out this ASP.NET AJAX control called PostBack Ritalin from a fellow SO'r Dave Ward. This could help you with an already tested solution to your javascript disabler idea.
Assign a unique ID in the form for the comment, and record it with the comment in the database. Perform a check on comments with that unique ID before performing your insert if it doesn't exist.
To allow a user to have several replies on a site active at once, you could allocate the token server-side initially, put that into a list of active posting tokens on the session for that user, put it into the hidden field on the comment form, and only allow a form submission to insert into the database if that token is in the list on the session (and remove it from the list on the session after successfully inserting into the database).
This saves you on ever storing the posting token in the database as above, which is a little easier but tatty.
Put a unique index on the natural key of the data to prevent duplicates from being entered. If required put it against all the fields of the table (except any date oriented ones that would receive the system date at the time of the insert or fields used only by the back end such as insertedby which would contain the user id of the person doing the insertion)except the id.
Select a natural primary key from one or more columns of the input data stream. Declare a primary key constraint on the table, using these columns. If you already have a primary key constraint on a surrogate key, and you don't want to remove it, declare a UNIQUE constraint on the natural key instead.
This will cause an error when the application attempts to insert a duplicate row into the table. You will however have to program the app to field the error, and do the right thing.
Related
I'm currently trying to implement a table within my SQL database. I'm looking to create a table that can be used to check if a user on my website has liked a post. The idea is to have a table with one axes iterating the posts on the website and one axis with the userID values iterated. Then in each box hold a binary value as to whether they have liked it. I'm just wondering how I would implement this. I have been doing this in C# by creating classes and converting these into server side code using Entity Framework 6.4.0.
Any help would be great.
What you are suggesting is a normalized structure for your use case; it would, for example, require adding more columns to the table everytime a post is added to the database (or a user, depending on whether you use rows or columns).
A typical database solution would be a bridge table, that represents the many to many relationship between posts and users.
Say table user_like_posts, with the following columns:
user_id -- foreign key to the "users" table
post_id -- foreign key to the "posts" table
You may want to add additional columns to the bridge table, like the timestamp when the user liked the post, or the-like.
Will every user have an opinion on every post? If not then you don't have the data you described. If users and posts are not related one to one then you have a simple relation. For each post that a user likes (or dislikes?) there is an entry for that user:
Likes/Dislikes Table:
User identifier
Post identifier
The binary value that indicates like or dislike
If the table only indicates 'likes' then you don't need the last column.
A design like this would work even if every user and every post is in this table. The table might get large in a hurry and keep growing every time you introduced a new post. But if this table only includes actual 'likes' (and/or 'dislikes') it should be manageable.
For a class you just have an enumerable that has the posts 'liked' (and possibly another that indicates the posts 'disliked.')
Think about what you are trying to represent. Ask yourself questions. Don't just latch on to an idea and try to 'do' it.
Will every user have an opinion of every post?
Do you need to store both 'likes' and 'dislikes?'
Can there be a 'neutral' opinion on a post?
Can users change their opinions?
You can only discover the correct data structure by asking and answering all the questions that matter to your situation (my list is not exhaustive - it is only an example.)
I have a table and it has one of the attribute set as identity. I want to get the value of the identity attribute that would be generated after I enter a value to the database.
I have EmpTable made of EmpID and EmpName. EmpID is set as Identity. I want to fetch the EmpID value before inserting a new row to the database.
I would advise against trying to do this with a table that is set up to use an integer column as the primary key. You will run into concurrency problems if you simply fetch the previous ID and increment it. Instead you should use a GUID (uniqueidentifier in SQL) as your primary key.
This will allow you to generate a new GUID in your code that can safely be saved to the database at a later stage.
http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx
http://msdn.microsoft.com/en-us/library/ms187942.aspx
Sure the server knows where the auto-increment count is in its sequence, but there is almost nothing useful you can do with that information. Imagine you go to the Post Office and they hand out numbered tickets so they can serve customers in order. Of course you could ask them what the next number they'll give out is, but since anyone can walk in at any time you don't know you'll get that number. If you don't know that you'll get it, you can't do anything with it - e.g. writing it as a reference number on a form would be a mistake.
Depending on what you're trying to do, your two main options are:
Use a client-generated guid as your identifier. This kind of messes up the order so the analogy isn't great, but imagine if each customer who walked in could generate a random number that they are sure would never have been used before. They could use that to fill out forms before taking a number.
Take a number, but do it in a transaction with the other operations. A customer can take a number and use it to fill out some paperwork. If they realize they left their money at home, they just throw everything away and you never call their number.
Why do you think you need this information? Can you use either of these strategies instead?
In my business logic, there is a function that creates a unique value (it is a session id) by a random function.
I have to be sure, that the session id is unique before I store them into database.
So I am generating new session id, until I found one, that is not yet in database.
But there might be a race condition between checking for existing session ids in database and writing it.
The functions for writing and reading in database are using two different connections.
How can I manage this?
I cannot use auto increments, because the next session should not be guessable.
I think you can make this column UNIQUE (add database constraint), try to insert new row and check wheter it will return an error about duplicate value. Considering that duplicates are very rare it's probably the fastest and safest method.
I have an ASP.Net form and I want to send an email when the user changes their data. The email should only include data that has changed, and there are about 15 data fields total.
I don't want to use an ORM since I am updating a website that a 3rd party built for us, and all their data access calls go through a custom library of theirs.
The only ways to do this I can think of is
Make another database call to get old values and compare the form values one-by-one. If they're different, append to the email.
Store original data somewhere when it's first loaded (hidden field, session, etc), and once again compare the data one field at a time and append the differences to an email
Have someone on SO tell me there's an easier and/or simpler way that I haven't thought of
All the text boxes will have a TextChanged event, you can have them mark themselves as modified. ComboBox's will have a SelectedIndexChanged event, and so on.
Edit: All changed events can check their initial values (even on reverted changes) and either mark themselves as still modified or on a revert, as un-modified.
Here are some suggestions that may / may not be useful:
Trigger on the database table and the trigger compares the old (using the DELETED table) and updated (using the INSERTED table) and then sends an email. This may or may not be viable and I am not a big advocate of triggers.
Like you have already said you could make another database call, which would be my reccommended approach.
From what you've said I think that the only way forward is to create a duplicate dataset on the form to store the old data and run a comparison at the point where you want to produce the email.
You can use Dataset.Copy to copy structure and data.
However, now that I think about it there's always the Datset.GetChanges() method and the Dataset.AcceptChanges() along with DataSet.HasChanges()
Example code from this link:
if(dataSet.HasChanges(DataRowState.Modified |
DataRowState.Added)&& dataSet.HasErrors)
{
// Use GetChanges to extract subset.
changesDataSet = dataSet.GetChanges(
DataRowState.Modified|DataRowState.Added);
PrintValues(changesDataSet, "Subset values");
// Insert code to reconcile errors. In this case, reject changes.
foreach(DataTable changesTable in changesDataSet.Tables)
{
if (changesTable.HasErrors)
{
foreach(DataRow changesRow in changesTable.Rows)
{
//Console.WriteLine(changesRow["Item"]);
if((int)changesRow["Item",DataRowVersion.Current ]> 100)
{
changesRow.RejectChanges();
changesRow.ClearErrors();
}
}
}
}
// Add a column to the changesDataSet.
changesDataSet.Tables["Items"].Columns.Add(
new DataColumn("newColumn"));
PrintValues(changesDataSet, "Reconciled subset values");
// Merge changes back to first DataSet.
dataSet.Merge(changesDataSet, false,
System.Data.MissingSchemaAction.Add);
}
PrintValues(dataSet, "Merged Values");
Imagine an object with a field that can't have a duplicate value in the database. My first instinct was to create a unique attribute that I could apply as a data annotation to a property. This unique attribute would hit the database and check if the value already exists. This would work when executing a create method, but would fail on an update. On an update, I would get a duplicate value error for every unique field of my entity whose value I don't want to change. What would be a good way, or an established practice, to accomplish this on ASP.NET MVC 2 in a way that fits nicely with the ModelState? Passing the id of my object to the attribute validator could work by checking if the duplicate value that is found is of the same entity that I am updating but I don't know how to get that data from inside of the validator.
Please forgive me if this is a stupid question or if it is phrased incoherently. It's almost 3 in the morning and I've been coding since the morning of yesterday.
For this kind of validation, I would let the database do what it already does so well. Make sure your database has the unique constraint and let it report back an error if you violate it. You can then add the error to the model errors (with a nice friendly bit of text, rather than just plonking the SQL error).
If you are determined to perform a check yourself, you can get around the UPDATE problem by excluding the current record...
SELECT COUNT(*)
FROM myTable
WHERE myTable.UniqueValue = 'ShouldBeUnique'
AND myTable.Id <> 5
In this example, you use the id of the record you are updating to avoid checking it, which means you just check other records to see if they contain the unique value.