Sqlite генерирует нулевое исключение при одном чтении БД, но не при другом - PullRequest
0 голосов
/ 30 октября 2018

У меня есть два оператора SELECT в блоке кода VB.NET sqlite.

Первый блок возвращает значение, второй возвращает нулевую ссылку, исключение объекта. Обе таблицы имеют одинаковые столбцы даты. Они из двух разных таблиц в одной БД. параметры ссылаются от и до "Datetime Picker". БД установлен как ДАТА. вот блоки.

Любая помощь?

Using con As New SQLiteConnection(connstring)
    con.Open()
    Using cmd As New SQLiteCommand
        cmd.Connection = con
        cmd.CommandText = "Select Count(*) from clientinfo where ID  > 0 "
        If cmd.ExecuteScalar = 0 Then
            Exit Sub
        Else
            ' add selected leads
            cmd.CommandText = "Select Count(LeadID) ld From Leaddata where  Capptdate between @dtfrom22 and  @dtto22 "
            cmd.Parameters.Add("@dtfrom22", SqlDbType.Date).Value = dtstatsfrom.Value
            cmd.Parameters.Add("@dtto22", SqlDbType.Date).Value = dtStatsTo.Value
            Dim RDR As SQLiteDataReader
            RDR = cmd.ExecuteReader
            Using RDR
                txtstatstotalleads.Text = 0
                While RDR.Read()
                    txtstatstotalleads.Text = RDR.Item("ld").ToString()
                End While
            End Using
            'add selected Sales
            cmd.CommandText = "Select Count(SalesID) sd From Salesdata  where  saledate between   @dtStatsFrom23 and   @dtStatsTo23 "
            cmd.Parameters.Add("@dtStatsfrom23", SqlDbType.Date).Value = dtstatsfrom.Value
            cmd.Parameters.Add("@dtStatsto23", SqlDbType.Date).Value = dtStatsTo.Value
            RDR = cmd.ExecuteReader
            Using RDR
                txtStatsSales.Text = 0
                While RDR.Read()
                    txtStatsSales.Text = RDR.Item("sd").ToString()
                End While
            End Using
            'Add avg COMMISION TO stats FORM
            cmd.CommandText = "Select Avg(CommissionAmt) cm From SalesData where saledate between @dtfrom24 and @dtto24"
            cmd.Parameters.Add("@dtfrom24", SqlDbType.Date).Value = dtstatsfrom.Value
            cmd.Parameters.Add("@dtto24", SqlDbType.Date).Value = dtStatsTo.Value
            RDR = cmd.ExecuteReader
            Using RDR
                txtStatsCommAvg.Text = 0
                While RDR.Read()
                    txtStatsCommAvg.Text = RDR.Item("cm").ToString()
                End While
            End Using
        End If
    End Using
End Using

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Попробуйте очистить коллекцию параметров перед добавлением новых параметров. Также попробуйте изменить имя читателя, чтобы убедиться, что у вас есть новое.

'Add avg COMMISION TO stats FORM
cmd.CommandText = "Select Avg(CommissionAmt) cm From SalesData where saledate between @dtfrom24 and @dtto24"
cmd.Parameters.Clear '<<--Add This
cmd.Parameters.Add("@dtfrom24", SqlDbType.Date).Value = dtstatsfrom.Value
cmd.Parameters.Add("@dtto24", SqlDbType.Date).Value = dtStatsTo.Value
'Put the using statement before you use assign the reader
Using RDR1 As New SQLiteDataReader 'Just try changing the name of the reader
    RDR1 = cmd.ExecuteReader
    txtStatsCommAvg.Text = 0
    While RDR1.Read()
             txtStatsCommAvg.Text = RDR1.Item("cm").ToString()
    End While
End Using
0 голосов
/ 01 ноября 2018

После исправления ошибок в соответствии с Джоэлом Коухомом, ответ, который работал, создавал скрытые текстовые поля в форме, связанной с указателем даты, и из нее. Затем я смог отформатировать текстовое поле, чтобы избежать формата даты и времени средства выбора и соответствовать строковому формату даты базы данных в Sqlite. Вот пример блока кода, который работает нормально. Все остальные текстовые поля в форме теперь заполнены соответствующими значениями.

enter  cmd.CommandText = "Select  A.num, A.Denom, Cast(A.num as Float)/Cast(A.Denom as float) as rnp From(Select(Select CAST(count(Result) as Decimal(5,2))" _
                        & "from LeadData  where (Result = 'Refusal')and CApptDate between @dtfrom49 and @dtto49 as num," _
                        & "(select cast(count(leadid) as decimal(5,2))  from LeadData  where  CApptDate between @dtfrom50 and @dtto50) as Denom)A "
                    cmd.Parameters.Add("@dtStatsfrom49", SqlDbType.Date).Value = txtStatsFrom.Text
                    cmd.Parameters.Add("@dtStatsto49", SqlDbType.Date).Value = txtStatsTo.Text
                    cmd.Parameters.Add("@dtStatsfrom50", SqlDbType.Date).Value = txtStatsFrom.Text
                    cmd.Parameters.Add("@dtStatsto50", SqlDbType.Date).Value = txtStatsTo.Text
                    RDR = cmd.ExecuteReader
                    Using RDR
                        txtStatsRefusalPercent.Text = 0
                        While RDR.Read()
                            txtStatsRefusalPercent.Text = RDR.Item("rnp").ToString()
                        End While

                    End Usingcode here
0 голосов
/ 30 октября 2018

Самое важное здесь , вы никогда не выполняете второй запрос . Вам нужно снова позвонить cmd.ExecuteReader().

Но есть и еще кое-что. Это With здесь не так:

With RDR.Read
    txtStatsSales.Text = RDR.Item("sd").ToString()
End With

Это на самом деле не проверяет результат функции Read() (и сейчас в современном VB более идиоматично всегда использовать круглые скобки с вызовами функций). Вы, вероятно, хотели это:

If RDR.Read() Then
    txtStatsSales.Text = RDR.Item("sd").ToString()
End If

Кроме того, здесь чаще используется цикл While, , даже если вы ожидаете только одну (или нет) запись , и в этой ситуации проверять HasRows не нужно и не полезно. Кроме того, AddWithValue() может вызвать проблемы с производительностью, если не использовать его осторожно (вероятно, в данном конкретном случае это нормально, но полезно иметь привычку использовать этот другой шаблон):

'add selected Sales
cmd.CommandText = "SELECT Count(SalesID) sd FROM Salesdata WHERE saledate BETWEEN @dtStatsFrom23 AND @dtStatsTo23"
cmd.Parameters.Add("@dtStatsfrom23", SqlType.Date).Value = dtstatsfrom.Value
cmd.Parameters.Add("@dtStatsto23", SqlType.Date).Value = dtStatsTo.Value

Using RDR = cmd.ExecuteReader()
    txtStatsSales.Text = 0
    While RDR.Read() 
        txtStatsSales.Text = RDR("sd").ToString()
    End While
End Using

На основании обновления вопроса я предлагаю начальную ревизию, как показано ниже. Это не все исправит, но даст нам лучшую основу для работы. Кроме того, чтобы действительно предлагали полное исправление, мне нужно увидеть образец значений даты, поскольку они хранятся в таблицах.

Using con As New SQLiteConnection(connstring), _
      cmd As New SQLiteCommand("SELECT Count(*) FROM clientinfo WHERE ID > 0", con)

    con.Open()
    If CInt(cmd.ExecuteScalar()) = 0 Then Exit Sub

    cmd.CommandText  = "SELECT Count(LeadID) ld FROM Leaddata WHERE Capptdate between @dtFrom and @dtTo;" & vbCrLf
    cmd.CommandText &= "SELECT Count(SalesID) sd, Avg(CommissionAmt) cm FROM Salesdata WHERE saledate between @dtFrom and @dtTo;"

    cmd.Parameters.Add("@dtFrom", SqliteType.Text).Value = dtstatsfrom.Value
    cmd.Parameters.Add("@dtTo", SqliteType.Text).Value = dtStatsTo.Value
    Using RDR As SQLiteDataReader = cmd.ExecuteReader()
        ' add selected leads
        txtstatstotalleads.Text = "0"
        While RDR.Read()
            txtstatstotalleads.Text = RDR("ld").ToString()
        End While

        RDR.NextResult()

       'add selected Sales and avg commission
        txtStatsSales.Text = "0"
        txtStatsCommAvg.Text = "0"
        While RDR.Read()
            txtStatsSales.Text = RDR("sd").ToString()
            txtStatsCommAvg.Text = RDR("cm").ToString()
        End While

    End Using
End Using

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

Но мне все еще нужно посмотреть образцы данных из таблицы, чтобы узнать, как эти даты действительно отформатированы. dtStatsFrom.Value и dtStatsTo.Value являются значениями DateTime, и сейчас вы получаете результат по умолчанию ToString(). Нам нужно явно вызвать .ToString() для этих значений, используя перегрузку, которая указывает точную строку формата, которая нам нужна для соответствия данным в таблице ... и мы должны надеяться, что данные отформатированы таким образом, чтобы это практично. Если у вас есть первый в месяц формат, распространенный в США, выражения BETWEEN по-прежнему обрабатывают их как string , а не даты , и вы не увидите ожидаемых результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...