Linq to sql unhandled exception from update stored procedure - c#

I have a simple Linq dbml class, containing 1 table. First I have it configured to "Use runtime" to do the updates. Throgh the UI, I'm intentionally updating a column to a wrong value. Then calling dataContext.SubmitChanges throws an error, which is caught in a catch=block, showing a MessageBox "The UPDATE statement conflicted with the CHECK constraint ...", as it should. So, everything is fine.
Then I change the update behaviour to "Customize" and use a simple update stored procedure (just 1 simple update statement). Updating through the UI with correct values works like a charm. The update sproc is called and everything is fine. But when entering this wrong value through the UI, and then pressing update, I get an unhandled exception on this line of code (internal code of the Linq class):
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())), field1, field2, ...);
Title: Exception User-Unhandled System.Data.SqlClient.SqlException:
'The UPDATE statement conflicted with the CHECK constraint
"CK_tblRitCentraal". The conflict occurred in database "RCS", table
"dbo.tblRitCentraal", column 'RitOpmerkingen'.
The statement has been terminated.'
Any help is greatly appreciated!

thanks for your reply. You are right, that my problem is, that the exception in yhe second case is not caught, even though it is exactly the same error as in the first case.
In the meantime I solved my problem. All I had to do was tick "do not break on this type of exceptions". Now the exception is nicely put through to the UI, and I can take care of it.
Still, I can't understand why. But hey, it got solved, so I shouldn't complain.

Related

Determine record exist by exception of SQL is Principles?

I have a table with primary key and I want to insert new record to that.
In my code, I check if record exists by exception. In the SQL stored procedure, I have insert code and surround by exception, in my application I execute that stored procedure and want to insert new record, if my record exist in table, insert code throws an error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Sup_Item_Sup_Item_Cat". The conflict occurred in database test, table test. The statement has been terminated.
and goes to the catch block.
In my application I check the error that was returned by SQL, and it shows a message box to user that record is exist.
I want to know, is this way is Principles? or I must use if exist statement in SQL?
Exception should never be used when you can avoid it and return a value.
Exception is a "stress" on a system and much slower than any other way.
Its customary for a SP to return 0 if everything is Ok and a negative value if there is an error.
Either check your SP return code in application or use out parameter to determine problem. An error should be truly an error.

Receiving different SqlException in Windows service to expected

I'm having a very strange issue. I have windows service which is failing because of a SqlException: "String or binary data would be truncated." for an INSERT statement.
Now this is a fairly basic error to solve but it is not the true error. If I do a trace and run the query straight on the database - there is NO error. All of the data in WAY shorter than the restrictions on the database.
I eventually took out some of this required columns from the query hoping to generate a different error: "Cannot insert the value NULL into column 'Type'"
I don't however get this error! I am still getting "String or binary data would be truncated."
I DO get this error if I run the query from the trace straight on the DB.
Does anyone have any ideas on what could be happening here? Thanks!
Edit to add
Here's the query that is supposed to give me the cannot insert value error. The other query is the same but with more parameters:
declare #p4 int
set #p4=60029550
exec sp_executesql N'EXECUTE ssl_GetTTDVersionCallSeq 1, #TTDVersionIDVal OUTPUT
INSERT INTO TTDVersion(Task,ID) VALUES (#P0,#TTDVersionIDVal)',N'#P0 int,#TTDVersionIDVal int output',#P0=200003762,#TTDVersionIDVal=#p4 output
select #p4
Found the cause of this error. It was not at all in the query posted above. There was a trigger on the table which set the LastUpdatedBy column.
Most of the users have a 4 char user name but the user that the service was being run as didn't. The column limit was 4.
Avoid this issue:
Triggers can be problematic. They aren't immediately visible - sp_help 'table' doesn't even return them. If they error you can't even trace the query.
What I should of tried earlier:
Running the query as the user. (I wanted to but it's an admin user and someone else was using it at the time.)
Checking all columns info vs what was in them and what was in the query. Then to check how that info is getting there. In this case a default constraint probably would of given same issue.

How to ignore LINQ to SQL on unique key?

I insert data with LINQ to SQL on my DB on a table where there is a unique key on 2 columns.
When I try to insert a row with this unique key already inserted, I get:
Cannot insert duplicate key row in object 'dbo.613_LiveLove' with
unique index 'IX_613_LiveLove'. The duplicate key value is
(35715346455553, paul). The statement has been terminated.
I don't want this error message, just "LINQ to SQL, does not insert it" and continue the process.
Is there a way on doing this? Or need I to use try/catch?
This might help: http://msdn.microsoft.com/en-us/library/bb425822.aspx#linqtosql_topic18
"... any errors detected by the database will cause the submission process to abort and an exception will be raised. All changes to the database will be rolled back as if none of the submissions ever took place. The DataContext will still have a full recording of all changes so it is possible to attempt to rectify the problem and resubmit them by calling SubmitChanges() again..."
Use try catch. Catch the specific exception type, and throw your own exception (you propably want to create your own exception type) including your custom message. At the location in you code you want to continue the process, just catch that exception.

Is it OK to just TRY and add a column to an SQL Server database and catch the exception?

Using SQL Server in C# is it worth saying:
IF COL_LENGTH('MyTable','MyColumn') IS NULL
BEGIN
ALTER TABLE MyTable ADD MyColumn INT
END
because I could more easily put a catch around the call:
try
{
Db.ExecuteNonQuery("ALTER TABLE MyTable ADD MyColumn INT");
}
catch(Exception)
{
}
and just let if fail all the time (except when running on an old database) ...
or is that naughty/slow/etc?
Exceptions should be "exceptional", as in the exception to the rule.
Do you plan on running this code, and 90% of the time, the column exists?
Then that is not "exceptional".
Do not use exception catching as normal logic flow.
Here are some more pointers by someone smarter than me:
http://blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx
"Do not use exceptions for normal flow of control. "
Here is my typical idempotent add column tsql.
IF EXISTS ( SELECT TABLE_SCHEMA , TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Categories' and TABLE_SCHEMA = 'dbo' )
BEGIN
IF NOT EXISTS
(
SELECT *
FROM [INFORMATION_SCHEMA].[COLUMNS]
WHERE
TABLE_NAME = 'Categories'
AND TABLE_SCHEMA = 'dbo'
AND COLUMN_NAME = 'CategoryName'
)
BEGIN
print 'Adding the column dbo.Categories.*CategoryName*'
ALTER TABLE [dbo].[Categories] ADD [CategoryName] nvarchar(15) NOT NULL
END
ELSE
BEGIN
print 'The column dbo.Categories.*CategoryName* already exists.'
END
END
Just don't catch the Exception exception this way: you'll never know if it is thrown:
because the table doesn't exists
because the column already exists
because the connection string is wrong
because of a network error
any other reason
If you want to create a column only if it doesn't already exists, do write the SQL that checks the presence of the column before adding it.
Does speed really matter in this case? How often do you update the database?
However, are you really sure that you want to silently eat ALL exceptions? The problem can be that you do not have DDL (modify db) permissions or that the column exists but with a different column type.
It's pretty standard to perform this type of check in your script because the script may need to be run more than once. For example, other table changes may get added to it. You don't want your script to cause errors if someone has to re-run it.
As others have noted, exceptions should be reserved for truly exceptional conditions.
But there's an additional problem in doing this in your C# code: you're mixing database maintenance stuff into what is (presumably) your application code. Your code is going to be much more readable and maintainable if you follow the principle of separation of concerns.
Your C# code flow is just a shallow shim around the back end, where the real work happens. As such, obvious questions arise:
WHY was an exception raised?
Reasons include, but are not limited to:
you do not have permission to alter the table
you timed out trying to obtain an SCH-M lock on the table
the new column triggers a size-of-data operation that runs out of log space
a custom DDL trigger prevents execution
a policy-based declarative management rule prevents execution
the IO subsystem just collapsed and database is offline
the column already exists (which seems to be the only case you thought of)
You are willing to silently swallow and silence the exception because you can only think at one possible reason to fail. When dealing with databases you are always in need of serious logging, otherwise you're just shooting yourself in the foot.
Is the exception free?
There is a long debate whether SEH is cheap or not, but this is completely beyond the point when talking about DDL in a database. You are requesting a SCH-M lock on an object and thus will block everybody until you get it. Even if your DDL throws and you handle the exception, you have already dipped the throughput to 0 (zero) while you waited for the uber lock to be granted. And you may had been waiting hours, you know...

getting {"could not execute batch command.[SQL: SQL not available]"} error from NHibernate

I took a look at other related posts but couldn't find any solution.
Sometimes on sesstion.Flush() I get the following error:
{"could not execute batch command.[SQL: SQL not available]"}
and the Inner Exception :
{"The UPDATE statement conflicted with the FOREIGN KEY constraint FK1377052553ABF955. The conflict occurred in database ProcessDebug, table dbo.Adjustment, column 'AdjustmentId'.The statement has been terminated."}
a piece of Process class mapping :
References(p => p.CurrentAdjustment)
;
References(p => p.DefaultAdjustment)
;
HasMany(p => p.Adjustments)
.Cascade.AllDeleteOrphan()
.Inverse()
;
All these properties above are of type of Adjustment.
As long as I get this error once in a while I couldn't track it down. For an entity it might happen now, but not next time in a same piece of code....
Any idea what might cause the problem?
I'm using NH 3.2 and FluentNhibernate
Thanks in advance
In my situation, it was "NULL" in one of the databese columns. Check your database data.
FOREIGN KEY -> this means, that you propably have null i column, that is use for "join".
p.s. Take SQL Profiler and check the SQL generated by nHibernate.
You need to look at the sql that is actually trying to execute.
It appears as though you are trying to update the primary key ("AdjustmentId") to something that does not exist. Hence the foreign key violation.
it seems about you database, not your nHibernate codes, check the SQL in log file, and try to exec it
To find the actual cause, you'll need to see the SQL that is being generated by nHibernate. You can either use nHibernate log or nHibernate profiler to get these SQL. Few of the common issues related to the above error message, include:
String or binary data would be truncated. An example of this issue is whenever you provide a string value that is larger than the defined varchar/nvarchar field size in database.
Expected primary or foreign key value is null
may be its not NHibernate problem!
please check in database which column is Not Null/Null. For this,I set null those columns.
You can do anything! set value when insert or set null on those column on table.
In my case I'm adding a data with column whose type is DateTime,
I insert 2100/2/2 get this error, but when insert more reasonable time 2001/2/2 get success,
so maybe the problem is in your data, and should follow some rule in database.

Categories