String.IsNullOrEmpty VS IsDBNull при проверке при использовании IIF и IF ELSE

Мне это непонятно, поэтому, если кто-нибудь может подробно объяснить, в чем разница между двумя функциями (IsDBNull и String.IsNullOrEmpty) VB.Net.

Ниже приведен мой сценарий, почему я спрашиваю об этом, у меня есть столбец Company в моей таблице, значение которого равно NULL, затем я использовал функцию IIF vb.net для проверки, если это NULL, затем назначьте пустую строку (""), иначе назначьте значение из таблицы данных

Сценарий:

  1. #P4# <блочная цитата> #P5#
    txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
    
  2. Однако, когда я заменяю String.IsNullOrEmpty на IsDBNull, проверка работает нормально.

    txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))
    

ИЗМЕНИТЬ:

И это сбивает с толку, потому что, если я выполнил проверку, используя условие IF ELSE (см. пример кода ниже) с использованием String.IsNullOrEmpty, все работает нормально.

    If String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) = True Then
        txtCompany.Text = ""
    Else
        txtCompany.Text = dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString
    End If

Смущает то, что когда я использовал IIF(String.IsNullOrEmpty...etc), он возвращает ошибку. но когда я использовал обычный IF String.IsNullOrEmpty(dtSample.Rows....etc) = True, он работал нормально.

Любое объяснение будет высоко оценено. Спасибо


person japzdivino    schedule 13.10.2015    source источник
comment
stackoverflow.com/questions/4958379/   -  person NoAlias    schedule 13.10.2015
comment
@NoAlias ​​я видел это, но это NULL , system.dbnull .. что мне не ясно, так это разница между String.IsNullOrEmpty и IsDBNull в моем приведенном выше сценарии.   -  person japzdivino    schedule 13.10.2015
comment
Этот вопрос возникает из-за того, что для параметра строгого компилятора отключено значение, выбранное новичком.   -  person Bjørn-Roger Kringsjå    schedule 13.10.2015


Ответы (4)


Вы не можете смешивать и сочетать String.IsNullOrEmpty и IsDBNull, потому что они работают над двумя разными вещами. Первый на строках, второй на элементах данных, считанных из базы данных.

Но очень важным элементом этого является то, что ваш код недействителен. Ни один фрагмент «Сценарий» не компилируется под Option Strict. Если вы оставите VB, чтобы угадать, что вы имеете в виду, вы получите запутанные результаты.

Фрагмент 1:

txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))

Упрощенный:

Dim foo = IIf(String.IsNullOrEmpty(zDT.Rows(23).Item("Name")).ToString,
                "", zDT.Rows(23).Item("Name"))

Это незаконно, потому что zDT.Rows(23).Item("Name") является объектом, а String.IsNullOrEmpty ожидает строку. Ваш ToString неуместен - он не преобразует элемент базы данных, он преобразует все выражение IIF bool!

Компилятор предупреждает вас об обоих withOption Strict On.

Преобразование вызывает исключение, поскольку VB должен преобразовать элемент базы данных Object ( zDT.Rows(23).Item("Name")) в строку. То, как это происходит, приводит к ошибке, когда данные базы данных имеют значение DBNull.

Фрагмент 2:

txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))

Упрощенный:

foo = IIf(IsDBNull(zDT.Rows(23).Item("Name")).ToString, 
               "", zDT.Rows(23).Item("Name"))

Это немного лучше, но вместо логического выражения пока используется строка. После исправления у вас есть:

IsDBNull(zDT.Rows(23).Item("Name"))

IsDBNull проверяет элемент базы данных (объект), чтобы узнать, есть ли в нем данные. Это будет работать. IsNullOrEmpty не следует использовать для проверки DBNull и не использовать с Option Strict. Сначала вам нужно преобразовать dbItem в строку, тогда он будет работать только в зависимости от того, как вы конвертируете.

' cant use string method to test an object
String.IsNullOrEmpty(zDT.Rows(23).Item("Name"))

' this will work:
String.IsNullOrEmpty(zDT.Rows(23).Item("Name").ToString)

' this will not:
String.IsNullOrEmpty(CStr(zDT.Rows(23).Item("Name")))

Используйте тесты DBNull для объектов данных и IsNullOrEmpty для строк.

Кроме того, если вы используете более новый оператор If вместо старой функции IIf, вы можете избежать других проблем. Оператор разрешает короткое замыкание, синтаксис такой же:

Dim foo = If(bool expr, True result, False result)
person Community    schedule 15.10.2015
comment
Ну наконец то! есть кто-то, кто очень хорошо меня понимает на основе моего примера :) Большое спасибо @Plutonix, теперь я понимаю, чем отличаются две функции и что я сделал неправильно в своем коде, я попробовал этот String.IsNullOrEmpty(zDT.Rows(23).Item("Name").ToString), и он работает, это означает, что я получаю ошибку раньше из-за неправильного преобразования объекта в строку с использованием String.IsNullOrEmpty, но правильное преобразование, когда я использовал IsDBNull, вы очень ясно объяснили это, упростив мой пример. Большое вам спасибо. :) - person japzdivino; 16.10.2015
comment
Это лучшее объяснение, так как оно очень хорошо понимает мой пример кода, и вы все объяснили, приняв это как ответ. Еще раз спасибо :) - person japzdivino; 16.10.2015

TL;DR

  • String.IsNullOrEmpty() проверяет только значения Empty ([blank], т.е. '' или "") или Null, но не проверяет DBNull, если какое-либо поле, поступающее из базы данных, имеет значение DBNull, это вызовет ошибку.
  • IsDBNull() проверяет наличие DBNull (это не то же самое, что Null)
  • .ToString преобразует DBNull в пустую строку, то есть ''

Подробности
Рассмотрите следующий пример таблицы SQL (используя SQL Server в качестве основы)

Структура таблицы:

Column_Name        Type and Size   Other Properties
----------------   -------------   ----------------------
Company_ID         int             IDENTITY(1,1) NOT NULL
Company_Name       nvarchar (50)                 NOT NULL   
Company_Address    nvarchar (50)                     NULL

ВСТАВИТЬ операторы:

INSERT [tbl_company] ([Company_Name], [Company_Address]) VALUES ('ABC', 'QWERT')
INSERT [tbl_company] ([Company_Name], [Company_Address]) VALUES ('ASD', ' ')
INSERT [tbl_company] ([Company_Name], [Company_Address]) VALUES ('XYZ', '')
INSERT [tbl_company] ([Company_Name])                    VALUES ('PQR')

Данные таблицы:

Company_ID    Company_Name      Company_Address
-----------   ----------------  ---------------
1             ABC               QWERT
2             ASD               [SPACE]
3             XYZ               [BLANK]
4             PQR               NULL

Тестирование Company_Address с помощью IsNullOrEmpty() и IsDBNull() с использованием SqlDataReader (r):

Company_ID IsNullOrEmpty(r("Company_Address")) IsDBNull(r("Company_Address"))
---------- ----------------------------------- ------------------------------
1          False                               False
2          False                               False
3          True                                False
4          ERROR                               True

А теперь конкретно по вопросу
Что здесь пытается сделать OP, давайте рассмотрим все утверждения по одному.

Оператор IIF с IsNullOrEmpty (неверно)

txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))

В этом операторе OP получает доступ к значению как dtSample.Rows(grdInfo.SelectedIndex).Item("Company") и проверяет его с помощью IsNullOrEmpty(), а затем преобразует результат IsNullOrEmpty в строку, используя .ToString, то есть IsNullOrEmpty(value).ToString(). Если значение равно DBNull, оно всегда будет возвращать ошибку. Правильный способ его использования

IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString)

См. последнюю часть Company")).ToString и Company").ToString), просто случай НЕУМЕСТНОГО ")"

Второе (IIF с IsDBNull) и третье (IF с IsNullOrEmpty) операторы OP верны

txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSample.Rows(grdInfo.SelectedIndex).Item("Company"))

If String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) = True Then
    txtCompany.Text = ""
Else
    txtCompany.Text = dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString
End If

Что касается второго оператора, OP правильно упорядочивает параметры, то есть первое поле Company преобразуется в строку с использованием dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString. Это преобразует любую строку DBNull в пустую строку, а затем проверяет IsNullOrEmpty. Теперь, когда значение уже преобразовано в EmptyString, оно не выдаст никакой ошибки.

Старые обсуждения с ОП

Разница очевидна в вашем тексте. Ваше первое утверждение:

txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString, "", dtSpecifierRebate.Rows(grdInfo.SelectedIndex).Item("Company"))

а второй

If String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) = True Then

Теперь разбейте их на части, первое утверждение (IIF)

String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString
'Item("Company")).ToString

И вторая часть (IF)

String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString)
'Item("Company").ToString)

Нашли отличия?
В первом операторе вы преобразуете результат IsNullOrEmpty в строку
Во втором вы преобразуете .Item("Company") в строку а потом сравниваем.

Если .Item("Company") возвращает DBNull
, то IsNullOrEmpty завершается ошибкой, поскольку .Item("Company") возвращает тип DBNull, тогда как IsNullOrEmpty проверяет null
IsDBNull работал, потому что он проверяет DBNull.

Все точки неуместной скобки ")" Это опечатка

Что касается использования вами этих операторов:
Если и IIF нужно проверять результаты как логические, а не как строки
Лучше рекомендуется удалить часть ToString ваших операторов.

person haraman    schedule 15.10.2015
comment
Тогда где IsDBNull часть вашего ответа? , вы фокусируетесь только на условии IF, IIF имеет 3 параметра, поэтому закрывающая скобка не ставится после .ToString, так как это только первый параметр, закрывающая скобка будет стоять после 3-го параметра IIF - person japzdivino; 15.10.2015
comment
Так должно было быть txtCompany.Text = IIf(String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")), "", dtSpecifierRebate.Rows(grdInfo.SelectedIndex).Item("Company")) . IsNullOrEmpty всегда будет давать сбой, если ваша база данных возвращает null (т.е. DBNull) для поля Company и txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")), "", dtSpecifierRebate.Rows(grdInfo.SelectedIndex).Item("Company")) - person haraman; 15.10.2015
comment
Или лучше IsDBNull как txtCompany.Text = IIf(IsDBNull(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")), "", dtSpecifierRebate.Rows(grdInfo.SelectedIndex).Item("Company").ToString). (Добавьте ToString в последнюю очередь). Я только что заметил два разных DT в вашем заявлении dtSample и dtSpecifierRebate. - person haraman; 15.10.2015
comment
Что касается вашего фокуса на IF и IIF, то это из-за их разной структуры в ваших утверждениях НЕМЕСТНАЯ скобка) (НЕ пропущено), что я уже объяснял выше. - person haraman; 15.10.2015
comment
просто игнорируйте dtSpecifierRebate, я изменил вопрос, чтобы удалить это, только dtSample, я сейчас тестирую его (удаляя .ToString) с использованием String.IsNullOrEmpty, если он будет работать. , потому что использование IsDBNull работает на мне, но мне было интересно, почему String.IsNullOrEmpty имеет ошибку преобразования, я вернусь к ней после тестирования. Спасибо - person japzdivino; 15.10.2015
comment
И помните, IsNullOrEmpty всегда будет выдавать ошибку преобразования, если поле Company в вашей таблице базы данных имеет значение DBNull, потому что значение типа DBNull не может быть преобразовано в строку, это ни пробел, ни пробел. Для значения, поступающего из таблицы базы данных, вы всегда должны использовать IsDBNull для проверки нулевых значений. - person haraman; 15.10.2015
comment
удаление .ToString не сработало, все еще возвращает то же сообщение об ошибке, запутанная часть находится в моем EDIT по вопросу выше, когда я использовал условие IF ELSE, он отлично работает, даже значение моей базы данных NULL, то есть я хотел знать , но я даю вам +1 голос за подробный ответ. - person japzdivino; 15.10.2015
comment
Сравните свое IIF утверждение String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company")).ToString и IF утверждение String.IsNullOrEmpty(dtSample.Rows(grdInfo.SelectedIndex).Item("Company").ToString) Просто проверьте скобки Company")).ToString и Company").ToString). Значение по-прежнему DBNull в Company")).ToString, и значение было преобразовано в EmptyString в Company").ToString) перед сравнением - person haraman; 15.10.2015
comment
Отличный улов dtSample.Rows(grdInfo.SelectedIndex).Item(Company)).ToString и хорошее объяснение в целом. - person NoAlias; 16.10.2015

Функция IsDBNull:

Возвращает логическое значение, указывающее, соответствует ли выражение классу System.DBNull.

IsDBNull возвращает True, если тип данных Expression соответствует типу DBNull; в противном случае IsDBNull возвращает значение False. Значение System.DBNull указывает, что объект представляет отсутствующие или несуществующие данные. DBNull — это не то же самое, что Nothing, что указывает на то, что переменная еще не инициализирована. DBNull также отличается от строки нулевой длины (""), которую иногда называют нулевой строкой.

пример :

 Dim testVar As Object 
   Dim nullCheck As Boolean
      nullCheck = IsDBNull(testVar)
     testVar = ""
     nullCheck = IsDBNull(testVar)
     testVar = System.DBNull.Value
    nullCheck = IsDBNull(testVar)
     '  The first two calls to IsDBNull return False; the third returns True..

Строка.IsNullOrEmpty:

Указывает, является ли указанная строка нулевой или пустой строкой. IsNullOrEmpty — это удобный метод, позволяющий одновременно проверить, является ли строка нулевой или ее значение пустым.

Пример :

    Class Sample
   Public Shared Sub Main()
  Dim s1 As String = "abcd"
  Dim s2 As String = ""
  Dim s3 As String = Nothing

  Console.WriteLine("String s1 {0}.", Test(s1))
  Console.WriteLine("String s2 {0}.", Test(s2))
  Console.WriteLine("String s3 {0}.", Test(s3))
   End Sub

   Public Shared Function Test(s As String) As String
     If String.IsNullOrEmpty(s) Then
     Return "is null or empty"
    Else
     Return String.Format("(""{0}"") is neither null nor empty", s)
    End If
   End Function 
 End Class  
     'The example displays the following output:
    'String s1 ("abcd") is neither null nor empty.
     'String s2 is null or empty.
      'String s3 is null or empty.
person Jayanti Lal    schedule 13.10.2015
comment
спасибо, но я все еще в замешательстве, потому что, когда я использовал IF ELSE, используя String.IsNullOrEmpy с логическим результатом, а не строкой, он работал нормально. поэтому мне было интересно, что IF ELSE и IIF влияют на проверку. - person japzdivino; 13.10.2015

Отношение IsNullOrEmpty проверяет, является ли строка пустой или нулевой. DBNull не равно нулю (ничего ), а скорее является классом, указывающим, что значение из базы данных не существует. IsDbNull проверяет, является ли значение равно DBNull.

Возможно, вы не получаете ошибку, о которой вы упоминаете в вопросе, в строке кода, на которую ссылается, поскольку у меня это работает очень хорошо:

        strTest = IIf(String.IsNullOrEmpty(DBNull.Value.ToString), "", DBNull.Value)
person NoAlias    schedule 13.10.2015
comment
мне до сих пор не ясно, я пытался использовать IF ELSE с String.IsNullOrEmpty, и он отлично работает. см. отредактированный вопрос выше. - person japzdivino; 13.10.2015
comment
Я отредактировал. Вы уверены, что получаете ошибку в строке кода, которую вы упоминаете в своем вопросе? - person NoAlias; 13.10.2015
comment
да, я уверен, что он возвращает ошибку, но когда я заменяю String.IsNullOrEmpty на IsDBNull, он отлично работает с условием IIF, но сбивает с толку то, что когда я использовал обычное условие IF ELSE, String.IsNullOrEmpty не возвращал ошибку. это работает нормально. - person japzdivino; 13.10.2015