У меня проблема, которую я просто не могу понять, мой Google-fu тоже меня не подвел, поэтому я подписал контракт, чтобы получить некоторую экспертную помощь.Сохраненная процедура возвращает null в VB
Проблема сложная, с несколькими красными сельдевыми, за то, что я могу понять, плюс, когда мы имеем дело с конфиденциальной информацией, я не могу дать точный код. Пожалуйста, не стесняйтесь, я постараюсь быть максимально точным и описательным.
Краткая версия проблемы. У меня есть хранимая процедура (на сервере SQL Server 2008 R2), которая возвращает одну строку при выполнении непосредственно на сервере. Когда одна и та же хранимая процедура выполняется с помощью кода VB.net (среда Visual Studio 2013), одно из значений столбца изменяется на DBNull.
Длинная версия с примером кода:
Вот очищены версия хранимой процедуры
Create PROCEDURE MySP
@inputParms [five of them]
AS
BEGIN
DECLARE @UserCanRun int
DECLARE @ThisApp INT
EXEC @UserCanRun = dbname.dbo.CheckUserCanRun @InputParm1, @ThisApp --security check
IF @UserCanRun = 0 --Means no problem, can continue
BEGIN
DECLARE @ExtraInfo varchar(100)
SELECT @ExtraInfo = typeID + ' - ' + typeName
FROM [three joined tables]
WHERE [conditions using some @InputParm4]
SELECT DISTINCT
col1, ..., [colN-1], @ExtraInfo as colN, [colN+1], ..., colM
FROM
[8 joined tables and subqueries]
WHERE
[more conditions with @InputParms2 to 5]
END
END
GO
Эта хранимая процедура выполняется только в порядке, когда выполняется непосредственно в базе данных; он возвращает одну строку, при этом вся (доступная) информация имеет правильное значение. (Вы заметите colN, это тот, который дает мне проблемы, сотрудники уверяют меня, что использование значения из переменной не должно быть проблемой.)
Теперь, когда я называю это с VB.net код:
dim rTable As DataTable
dim myCmd = New SqlCommand(SPName, myConnectionString)
dim parameter As SQLParameter
dim rValue As Integer = 0
[set SQL parameters]
If not myCmd is Nothing Then
If myCmd.Connection.State = connectionstate.Closed Then
[bit of security check code]
command.Connection.Open()
End If
Dim myAdapter As New SqlDataAdapter
myAdapter.SelectCommand = myCmd
myAdapter.Fill(rTable) 'problem!
ReturnValue = CInt(myCmd.Parameters(RETURN_VALUE_FIELD).Value)
End If
[more code]
Если я быстро смотреть на rTable
после команды myAdapter.Fill
исполнил, значение rTable.Rows(0).Item([M])
возвращает DBNull, в то время как это было не DBNull
когда принес непосредственно в СП, используя одни и те же параметры.
У меня нет набора данных для этой таблицы; вы можете увидеть, что он использует общий код DataTable
(код адаптирован из конкретного приложения для упрощения всех вызовов хранимых процедур, поэтому я не могу создать набор данных и использовать его на этом уровне). Поэтому я не думаю.
Я проверил действительность стоимости; Я даже проверил значение Unicode каждого символа значения @ExtraInfo
, чтобы убедиться, что не было какого-то контрольного символа, который был бы случайно введен. Он соответствовал показанным значениям, поэтому ни один плохой символ не испортил значение.
Это используется в нескольких местах кода, но, похоже, не работает для одного конкретного набора данных в нашей производственной среде; Я не смог воспроизвести проблему в нашей среде разработки. Поэтому я не могу просто пойти и поиграть с ним.
Может кто-нибудь знать, что еще может привести к тому, что значение столбца будет передаваться из непустого, непустого varchar
в DBNull, пройдя через SqlDataAdapter.Fill()
? Я не могу войти в этот призыв, поэтому я слепой.
(Также стоит отметить, может быть: я использовал VB.net всего около двух лет, отлаживая существующие системы, поэтому мне может не хватать чего-то очевидного, хотя мои более опытные коллеги тоже этого не понимают.)
Отредактировано, чтобы добавить окончательное слово о проблеме: Я никогда не находил решение, за исключением старого старого закона Мерфи. Отпустив это на некоторое время, я попросил сотрудника взглянуть. Когда я показывал ему, проблема не возникала. Еще один тест позже подтвердил, что он ведет себя нормально. Я не могу обещать, что закон Мерфи - это верное решение, но я могу только предположить, что была какая-то временная ошибка, которая исчезла сама по себе.Если это случится с вами, удачи и сообщите нам, если вы найдете решение или даже способ его диагностировать. Спасибо!
Вы сказали, что вы успешно запустили процедуру на сервере, но был он 'CheckUserCanRun' или это был' MySp', что вы были в состоянии работать? – ahwm
Вы забыли указать CommandType как CommandType.StoredProcedure? – Steve
Я запустил все это, так что MySp. Функция CheckUserCanRun - это проверка безопасности, чтобы убедиться, что неавторизованный пользователь не увидит данные. – PaDe