TSQL error in .Net but not in SSMS

让人想犯罪 __ 提交于 2019-12-11 09:22:37

问题


Having just built a c# application to run SQL scripts, I've run into a few issues with error handling.

We have a stored procedure in our database which modifies the default constraint for tables (by dropping any existing one and then creating the new one), and it runs fine when we call it from SSMS. However, when we call the same stored procedure from the .Net SqlClient, it gives an error. The error I get in the SqlException has the message:

System.Data.SqlClient.SqlException: Column already has a DEFAULT bound to it.
Could not create constraint. See previous errors.

This shouldn't happen, since we never see the message in SSMS unless we don't run the drop statement first. If the Drop Constraint statement is commented out, we see the same message.

Why would the constraint not get dropped when we call the stored procedure from in .Net?

For reference, the relevant code inside the stored procedure is:

  SELECT @strSQL = 'ALTER TABLE [' + @strTableName + '] DROP CONSTRAINT  [' + @strConstraintName + ']'
  EXEC sp_executesql @strSQL

  SELECT @strSQL = 'ALTER TABLE [' + @strTableName + '] ADD CONSTRAINT DF_' + @strTableName + '_' + @strColumnName + ' DEFAULT (' + @strDefaultValue + ') FOR ' + @strColumnName
  EXEC sp_executesql @strSQL

EDIT: I considered trapping for errors, and ignoring non-fatal errors such as this. However, unfortunately this specific error is a Level 16 error, and errors such as updating a non-existent table are only Level 15. So I can't let this error pass by filtering on the Error Class of the exception.

EDIT 2: Should have mentioned, the @strConstraintName is determined automatically based on the table name and column name:

SELECT
        @strConstraintName = vdc.CONSTRAINT_NAME
  FROM
        dbo.vw_DEFAULT_CONSTRAINT vdc
  WHERE
        vdc.TABLE_NAME = @strTableName
        AND vdc.COLUMN_NAME = @strColumnName

Resolution

So, it turns out that the vw_DEFAULT_CONSTRAINT that was determining the name of the default constraint was badly written.

It was filtering based on the value of USER_ID() for some reason (the view was written before I started) which wasn't necessary. Removing this restriction from the view returned the correct constraint name.

@ErikE's answer provided a good push in the correct direction. Saving the variable values into a temporary table allowed me to see that the 2 methods weren't actually working the same, which led me to investigate the view further. Kudos to @ErikE for this, which is why I selected his as the correct answer.

I do find it strange though that the value of USER_ID() was not the same, since the connections were identical.


回答1:


If running an SP-statement trace in SQL Profiler doesn't reveal a difference, can you log the @SQL variable contents being executed to a table and review them afterward? I'm really quite confused that they are truly identical.

Is it possible that the drop default constraint is failing due to a name problem? I think you answered this but it would be a plausible answer.

Did you know that dynamic SQL is executed with the permissions of the caller, not the SP owner, unless you take special measures (such as EXECUTE AS)? Could this be the issue?

Try commenting out the create default from the SP, running it from .Net, and seeing if the default was really dropped by the first statement. Or put a WAITFOR DELAY '5:00' in between them so you can check mid-run.




回答2:


Try tu use SQL Server Profiler and compare the query from the ADO.NET to your query from the SSMS.




回答3:


Try profiling the execution of the query and extracting the SET statements the SqlClient executes on connection. For example this is what I had profiled in the past when debugging performance differences of a query executed by the SqlClient versus running it in SSMS:

set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

Run these SET statements into SSMS and then try executing your query there again to see if you can replicate the behaviour. Whilst I don't believe this will surface your issue it is at least a good exercise to ensure your session configuration in SSMS is the same as if the query were being executed by the SqlClient



来源:https://stackoverflow.com/questions/9134739/tsql-error-in-net-but-not-in-ssms

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!