Обходной путь VB .Net NullReferenceException - PullRequest
6 голосов
/ 12 февраля 2012

Это должно быть просто, но у меня проблемы.Используя библиотеку eBay .Net, иногда определенные поля в ответе Nothing и иногда содержат значение.Когда они равны Nothing, их можно просто представить в виде пустой строки, но разработчики решили вернуть их как Nothing, поэтому, когда я пытаюсь установить значение String в значение (когда ничего не существует), я получаю исключение NullReferenceException, см.ниже

Imports System
Imports System.Configuration.ConfigurationManager
Imports System.Globalization
Imports System.Threading
Imports System.Xml

Imports eBay.Service.Core.Soap
Imports eBay.Service.Core.Sdk
Imports eBay.Service.Call
Imports eBay.Service.Util

Public Class eBayOrderImportService
Private Sub ServiceWorkerThread(ByVal state As Object)
    ' Periodically check if the service is stopping.
    Do While Not Me.stopping
        ' Perform main service function here...
        GetLastTime()
        Dim apiContext As ApiContext = GetApiContext()

        Dim apiCall As GetOrdersCall = New GetOrdersCall(apiContext)
        Dim orders As New OrderTypeCollection

        Dim timeFilter As New TimeFilter
        timeFilter.TimeFrom = lastUpdate
        timeFilter.TimeTo = Date.Now


        Dim lastTime As Boolean = SetLastTime()
        apiCall.IncludeFinalValueFee = True
        orders = apiCall.GetOrders(timeFilter, TradingRoleCodeType.Seller, OrderStatusCodeType.Completed)

        Dim order As OrderType

        For Each order In orders
            'do order-wide stuff here
            LogOrder(order)

        Next
        Thread.Sleep(30 * 1000)  ' Simulate some lengthy operations.

    Loop

    ' Signal the stopped event.
    Me.stoppedEvent.Set()
End Sub

Private Sub LogOrder(ByVal Order As OrderType)

    Dim OrderID, AccountID, BillingFirstName, BillingLastName, _
        BillingCompany, BillingEmailAddress, BillingPhone, _
        BillingAddress1, BillingAddress2, BillingCity, _
        BillingStateProvidence, BillingPostalCode, _
        BillingCountry, ShippingFirstName, ShippingLastName, _
        ShippingCompany, ShippingEmailAddress, ShippingPhone, _
        ShippingAddress1, ShippingAddress2, ShippingCity, _
        ShippingStateProvidence, ShippingPostalCode, _
        ShippingCountry, OrderStatus, BillingStatus, _
        OrderDate, ShippingMethod, SalesTax, _
        PreShippingCharge, OrderDiscount, OrderTotalCharged, _
        PaymentMethod, RepeatOrder, GiftCode, CouponCode, RID, _
        OrderNotes, OrderChannel, IsPrinted, IsShipped, PrintDate, _
        ShipDate, ActualShipCharge, DaysInTransit, DeliveryDate, _
        TrackingNumber, ShippedMethod As String


    OrderID = Order.OrderID

    AccountID = ""

    Dim name As String = If(Order.ShippingAddress.Name.ToString(), "None Given")

    BillingFirstName = name.Substring(0, name.IndexOf(" "))
    BillingLastName = name.Substring(name.IndexOf(" ") + 1)
    BillingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "")
    BillingEmailAddress = If(Order.TransactionArray(0).Buyer.Email.ToString(), "")
    BillingPhone = If(Order.ShippingAddress.Phone.ToString(), "")
    BillingAddress1 = If(Order.ShippingAddress.Street1.ToString(), "")
    BillingAddress2 = If(Order.ShippingAddress.Street2.ToString(), "")
    BillingCity = If(Order.ShippingAddress.CityName.ToString(), "")
    BillingStateProvidence = If(Order.ShippingAddress.StateOrProvince.ToString(), "")
    BillingPostalCode = If(Order.ShippingAddress.PostalCode.ToString(), "")
    BillingCountry = If(Order.ShippingAddress.CountryName.ToString(), "")
    ShippingFirstName = If(BillingFirstName, "")
    ShippingLastName = If(BillingLastName, "")
    ShippingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "")
    ShippingEmailAddress = If(Order.TransactionArray(0).Buyer.Email.ToString(), "")
    ShippingPhone = If(Order.ShippingAddress.Phone.ToString(), "")
    ShippingAddress1 = If(Order.ShippingAddress.Street1.ToString(), "")
    ShippingAddress2 = If(Order.ShippingAddress.Street2.ToString(), "")
    ShippingCity = If(Order.ShippingAddress.CityName.ToString(), "")
    ShippingStateProvidence = If(Order.ShippingAddress.StateOrProvince.ToString(), "")
    ShippingPostalCode = If(Order.ShippingAddress.PostalCode.ToString(), "")
    ShippingCountry = If(Order.ShippingAddress.CountryName.ToString(), "")
    OrderStatus = If(Order.OrderStatus.ToString(), "")
    BillingStatus = If(Order.OrderStatus.ToString(), "")
    OrderDate = If(Order.CreatedTime.ToString("MM/DD/yyyy"), "")
    If Order.TransactionArray(0).Taxes IsNot Nothing Then
        Dim tmpTax As Double = 0.0
        Dim tmpTrans As TransactionType
        For Each tmpTrans In Order.TransactionArray
            tmpTax = tmpTax + tmpTrans.Taxes.TotalTaxAmount.Value
        Next
        SalesTax = tmpTax.ToString()

    Else
        SalesTax = "0.0"
    End If


    ShippingMethod = If(Order.ShippingServiceSelected.ShippingService.ToString(), "")
    ShippingMethod = ShippingMethod & ":" & If(Order.ShippingServiceSelected.ShippingServicePriority.ToString(), "")

    OrderTotalCharged = If(Order.Total.Value.ToString(), "")
    OrderChannel = "eBay"
    comm = New OdbcCommand
    comm.CommandText = _
           "INSERT INTO Orders (OrderID, AccountID, BillingFirstName, BillingLastName, " & _
           "BillingCompany, BillingEmailAddress, BillingPhone, BillingAddress1, " & _
           "BillingAddress2, BillingCity, BillingStateProvidence, BillingPostalCode, " & _
           "BillingCountry, ShippingFirstName, ShippingLastName, ShippingCompany, " & _
           "ShippingEmailAddress, ShippingPhone, ShippingAddress1, ShippingAddress2, " & _
           "ShippingCity, ShippingStateProvidence, ShippingPostalCode, ShippingCountry, " & _
           "OrderStatus, BillingStatus, OrderDate, SalesTax, ShippingMethod, OrderTotalCharged, OrderChannel) " & _
           "VALUES('" & OrderID & "', '" & AccountID & "', '" & BillingFirstName & "', '" & _
           BillingLastName & "', '" & BillingCompany & "', '" & BillingEmailAddress & "', '" & _
           BillingPhone & "', '" & BillingAddress1 & "', '" & BillingAddress2 & "', '" & BillingCity & "', '" & _
           BillingStateProvidence & "', '" & BillingPostalCode & "', '" & BillingCountry & "', '" & _
           ShippingFirstName & "', '" & ShippingLastName & "', '" & ShippingCompany & "', '" & _
           ShippingEmailAddress & "', '" & ShippingPhone & "', '" & ShippingAddress1 & "', '" & _
           ShippingAddress2 & "', '" & ShippingCity & "', '" & ShippingStateProvidence & "', '" & _
           ShippingPostalCode & "', '" & ShippingCountry & "', '" & OrderStatus & "', '" & _
           BillingStatus & "', '" & OrderDate & "', '" & SalesTax & "', '" & ShippingMethod & "', '" & _
           OrderTotalCharged & "', '" & OrderChannel & "')"
    ' Dim orderResult As Integer = comm.ExecuteNonQuery()
    sysLog.WriteEntry(comm.CommandText)
End Sub
End Class

Обновлен код, обратите внимание, что исключение не выдается до тех пор, пока не будет выполнено: BillingCompany = If (Order.ShippingAddress.CompanyName.ToString (), "").Свойство Name имеет значение, которое успешно сохранено в его переменной, в то время как Order.ShippingAddress.CompanyName имеет значение Nothing (это свойство существует и иногда может иметь значение).Я обновил код, добавив в него ответ Энтони Пеграма, который не помог.

Все объявлено правильно, для сокращения кода я только что показал соответствующий пример.Рассмотрим это внутри цикла для каждого заказа, возвращаемого из вызова GetOrders (), иногда Order.ShippingAddress.CompanyName будет ничем, в такие моменты можно ли обрабатывать его как пустую строку?Я попробовал метод ToString ().На других языках я мог бы $ CompanyName = this ||что;

Что-нибудь похожее в VB .Net?

Ответы [ 2 ]

11 голосов
/ 12 февраля 2012

Вы можете использовать If(a, b), чтобы объединить ноль в другое значение.Пример:

Dim obj as String = Nothing
Dim foo as String = If(obj, "foo")

Вывод foo в этом примере будет строкой "foo".Если у вас есть ненулевая строка, назначенная для obj, то foo также будет ссылаться на эту строку.

Однако у меня есть сильное ощущение, что исключение вашей нулевой ссылки может происходить не для свойства, а для объекта.Order или ShippingAddress может быть нулевым.Доступ к свойствам или методам по нулевой ссылке является ошибкой.Простой доступ к нулевому значению путем сохранения его в переменной сам по себе не является ошибкой.

Если вы получаете исключение в одной из этих строк

CompanyName = Order.ShippingAddress.CompanyName 
State = Order.ShippingAddress.StateOrProvince

Это потому, что либоЗаказ или адрес доставки не указан.

Проверьте и посмотрите, могут ли эти объекты действительно возвращаться как ничего.Если это так, вам нужно применить проверку на нуль вокруг них, прежде чем получить доступ к их свойствам.


Ваше обновление:

Обновленный код, обратите внимание, что исключение не выдаетсядо тех пор, пока:

BillingCompany = If(Order.ShippingAddress.CompanyName.ToString(), "")

не будет выполнено.

Это может выдать, потому что Order может быть нулевым, ShippingAddress может быть нулевым, или CompanyName может быть нулевым. Это исключение для доступа к свойству или методу по нулевой ссылке. Если Order равен нулю, вы получите ошибку при доступе к ShippingAddress.Аналогично, если ShippingAddress имеет значение null, вы не можете получить доступ к CompanyName.Если CompanyName имеет значение null, вы не можете вызывать ToString ().

Вы должны в какой-то момент проверить, какой объект является нулевым.У меня нет уверенности, что ни один из них не будет нулевым.Вы? Проверка . Пошагово просматривайте вашу программу и наблюдайте за состоянием объекта.

Если все сводится к свойствам, таким как CompanyName, равным нулю, и если CompanyName - строка, пропустите вызов ToString ().

BillingCompany = If(Order.ShippingAddress.CompanyName, "")

Если CompanyName не является строкой, вам просто нужно сравнить ее с Nothing перед вызовом ToString () или доступом к свойству.

2 голосов
/ 12 февраля 2012

Посмотрите на эту строку:

CompanyName = Order.ShippingAddress.CompanyName

Если свойство CompanyName в Order.ShippingAddress.CompanyName равно Nothing, этот код все еще совершенно допустим и будет не срабатыватьисключение NullReferenceException.Исключение вызвано тем, что либо Order.ShippingAddress, либо Order само по себе является Nothing.Вы получаете исключение, потому что вы пытаетесь найти определенное свойство для объекта, который не существует.Исходя из примера кода, легко понять, почему это может иметь место:

Dim Order As OrderType

Эта строка объявляет переменную, но фактически никогда не дает этой переменной значение .Order - это переменная ссылки на объект ... которая еще не установлена ​​для экземпляра объекта.Теперь звучит так, как будто вы пропускаете код, в котором установлен экземпляр, но стоит упомянуть, потому что если это так, то это очень основная часть того, как этот код должен работать, и имеет смысл включить хотя бы заглушку для этого вобразец.

...