Not able to insert again after System.Data.UpdateException >> Unique Key - asp.net

I was working with LINQ in my asp.net application. I've putted a Unique Key on two columns of the 'ColorDV' table. When trying to add a duplicated value like 'ss' I've got the result:
System.Data.UpdateException: An error occurred while updating the
entries. See the inner exception for details. --->
System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint
'TITLE_AR_ColorDV'. Cannot insert duplicate key in object
'dbo.ColorDV'. The duplicate key value is (ss). The statement has been
terminated.
but the problem is that after this exception i can't insert any record in any of the tables, because of the same exact exception. I wonder if LINQ is trying to perform the same previous insert each time.
Please how can I solve this problem?

When you add an object to the ObjectContext, that object stays within the list of objects being submitted to the database, so yes that is the problem. Remove the object and continue, or if an edit try to use the Refresh method on the context to refresh the contents of the object to the original state.
This has an additional approach; can't personally say it works though.

Related

SQL: Best practice for inserting a record if it doesn't exist

I have an asp.net Gridview that handles insert operations into a SQL database. Records are only permitted to be inserted if they meet a uniqueness criteria, and this constraint is being enforced using unique indexes in SQL server. If the user attempts to insert a record that already exists, an error message is displayed.
I'm wondering what the best practice is for implementing this.
Check if the record exists SQL side, using IF EXISTS, and locking hints (updlock, holdlock, etc). Return an error code to ASP.net depending on whether the record was inserted
Perform the INSERT operation inside a SQL server try/catch block, relying on the unique index to prevent the insert from occurring if the record exists. Return an error code depending on whether an exception was thrown.
Perform the INSERT operation SQL side, but without SQL try/catch. Handle the PK violation exception inside ASP.net instead.
Normally I'd consider using exceptions to handle valid operations to be bad practice - i.e. software should not throw exceptions unless something is broken. However if the unique index on the table in SQL is going to implement the desired constraint, why bother performing a manual check for existence of the record?
I would make a separate call to check if the record already exists. If yes, show message to user, if no make insert. The reason I would do it this way is because I prefer keeping all the business logic in the application.
If you insist in making just one stored proc call:
I would check before I insert. I would also add an output parameter to the stored proc that returns a message if the insert was unsuccessful. In my application if I see a message in the output parameter, I will display that to the user.

Handling Exception

I have a temporary table with gridview( MaterialGrid) which inserts,update n delete values from grid on save button click.
Material_id is primary key for gridview n it does not allow duplicate material entry through combobox(which is in MaterialGrid),while inserting duplicate material it throws exception in bindmaterialGrid function.
I want to handle this exception n display message box
"cant insert duplicate material"
how to solve it?
Instead of throwing and catching Exceptions, you should have to check the existence of primary key column value.
Don't wait for exception to be thrown, rather have a check before hand and see if the value being inserted is already present. Using this approach, you will have more control on the execution flow and you will also avoid the overhead of processing exception.

How can this scenario cause an UpdateException in EntityFramework while calling SaveChanges?

I am unable to understand the line in bold from this msdn page:-
http://msdn.microsoft.com/en-us/library/bb738618.aspx
SaveChanges can generate an UpdateException when an object added to the ObjectContext cannot be successfully created in the data source. This can happen if a row with the foreign key specified by the relationship already exists. When this occurs, you cannot use Refresh to update the added object in the object context. Instead, reload the object with a value of OverwriteChanges for MergeOption.
In a table, a foreign key column can have a single value multiple times. e.g. DepartmentID foreign key in Users Table: More than one User can have same DepartmentID foreign key.
So how can this cause an UpdateException ?
Easy. You have an entity in your context in the Added state with a PK value of something already in the DB. This is common when people try to use stub objects incorrectly. If you want more help than that, you need to isolate your problem and post your code.

parsing SQLException errors in an ASP.NET (MVC) application?

While validation can prevent most SQL errors, there are situations that simply cannot be prevented. I can think of two of them: uniqueness of some column and wrong foreign key: validation cannot be effective as the an object can be created or deleted by other parties just after validation and before db insertion. So there are (at least) two SQL errors that should lead to a message of invalid user input.
SQLException has a Number property for the error type, but I don't know how to find out which column is duplicated or which foreign key is wrong without trying to parse the actual error message text, which happens to be localized.
Is there any way to identify the offending column other than parsing the error message (which means at least to strictly choose a language for SQL Server and always use it)?
edit:
I should mention that I come from RubyOnRails, where the approach is: let's pretend that the db doesn't exist: no constraints, no db-enforced foreign keys etc. As I'm approaching ASP.NET MVC, I'd like to get rid of the rails biases, and accept the fact that the db indeed exists.
Are you sure these two situations absolutely cannot be prevented?
You can avoid unique constraint SQLexceptions on Insert, by using an Identity (database generated) primary key column. SQL Server will guarantee that the value is unique.
The same goes for inserting related rows into tables linked by a foreign key. Insert a row in each referenced table first, before inserting a row in the main table. Use IDENTITY_INSERT to get the value of each auto generated primary key and use this as the foreign key in your main table.
You should also wrap these individual statements in a transaction to ensure that either all tables are inserted successfully or none are. The transaction also isolates (hides) these changes from all other concurrent database accesses until the transaction is committed.

is it possible to delete from 2 or more sql tables using a sql datasource?

I am getting an FK error when i am deleteing a row from my datagrid because i cant see a way to delete from the oher table where the FK is then the main table?
i am getting this error:
The DELETE statement conflicted with the REFERENCE constraint "FK_Availability_Fixture". The conflict occurred in database "Rugby", table "dbo.Availability", column 'FixtureId'.
The statement has been terminated.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK_Availability_Fixture". The conflict occurred in database "Rugby", table "dbo.Availability", column 'FixtureId'.
The statement has been terminated.
You can define your FK relationship to cascade on delete. This will result in the delete statement cascading (deleting) all child tables.
Check out page from MSDN
This is a "supposed to happen" to maintain data integrity: a row in another table references the row you're trying to delete.
If your delete succeeded, that other table's reference would make no sense.
The only way around this is to delete the referring row first (and this might mean deleting other rows that also refer to the row you're trying to delete.)
It's an indication that either: a) you shouldn't be deleting this row, b) or you need to delete other (potentially many other) row(s) first, or c) that your table design isn't correct for the use your trying to make of the database.
Your database is saying: "Do not allow the Availability.FixtureID column to reference values that don't exist." So, deleting a row from the Fixture table will be in violation of this when a row from the Availability table references it.
So you have two choices, either are equally vaid, but the first is probably what you're looking for:
Find the foreign key relationship named FK_Availability_Fixture, and then enable cascade delete on the FixtureId column.
Manually delete the dependancy row in the Availability table, or update the FixtureID for the particular row in question so that it references a different FixtureID value.

Resources