2017-01-31 42 views
0

私はSQLデータベースから読み込みますが、フィールドに応じて同じテーブルの別のフィールドを更新する必要があります。私は、データセットをループして、ループ中にUPDATEを返そうとしています。私のTESTテーブルで動作しましたが、私のプロダクションテーブルでは動作しません。 "ExecuteNonQuery"コマンドを実行すると、タイムアウト期限切れのエラーが発生します。実際に最初の接続を閉じてExecuteNonQueryを呼び出すと、即座に実行されます。VB.NETはDataReaderループ内の同じテーブルを更新します

は、ここで使用してクエリをパラメータ化し、その後SqlDbType.DatetimeSqlParameterを使用して、代わりにフォーマットされた文字列の本当のDateTimeを割り当て、文字列を連結していない

Public Class Form1 

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 

     Dim sqlConn As New SqlConnection 
     Dim sqlComm As New SqlCommand 
     Dim sqlDR As SqlDataReader 




     sqlConn.ConnectionString = "Data Source=10.2.0.87;Initial Catalog=Inbound_Orders_DB;User ID=xxxxx;Password=xxxxxx;" 
     sqlConn.Open() 
     sqlComm.CommandText = "SELECT * FROM RH_Orders where Order_DateTime is NULL ORDER by Order_Date DESC" 
     sqlComm.Connection = sqlConn 

     sqlDR = sqlComm.ExecuteReader 

     If sqlDR.HasRows Then 
      While sqlDR.Read 
       If Trim(sqlDR("Order_Date")) <> "" Then 
        Dim order_Date As String = Trim(sqlDR("Order_Date")) 
        Dim order_DateTime As String = "" 
        If Len(order_Date) = 14 Then 
         order_DateTime = order_Date.Substring(0, 4) & "-" & order_Date.Substring(4, 2) & "-" & order_Date.Substring(6, 2) & " " 
         order_DateTime = order_DateTime & order_Date.Substring(8, 2) & ":" & order_Date.Substring(10, 2) & ":" & order_Date.Substring(12, 2) 
         Dim myId As String = sqlDR("ID") 

         Dim sqlConn2 As New SqlConnection 
         Dim sqlComm2 As New SqlCommand 

         sqlConn2.ConnectionString = "Data Source=10.2.0.87;Initial Catalog=Inbound_Orders_DB;User ID=xxxx;Password=xxxx;" 
         sqlConn2.Open() 

         sqlComm2.CommandText = "UPDATE [RH_Orders] SET order_DateTime = '" & order_DateTime & "' WHERE ID=" & myId 
         sqlComm2.Connection = sqlConn2 

         sqlComm2.ExecuteNonQuery() 
         sqlConn2.Close() 

        End If 
       End If 
      End While 

     End If 


    End Sub 
End Class 
+0

パラメータ化されたクエリを使用し、文字列を連結しないで 'SqlParameter'を' SqlDbType.Datetime'で使用し、形式化された文字列の代わりに実際の 'DateTime'を割り当てます。 –

+1

'SqlDataAdapter.Fill(table)'でDataTableを埋めることができます。その後、テーブルの 'Rows'をループし、' DataRow'をそれぞれ変更し、 'SqlDataAdapter.Update(table)'を使用してループの後にすべての変更を1つのバッチで送ります。 SqlDataReaderループの必要はありません –

+0

ここでもループが必要なものは何も表示されません。すべての行を一度に更新する通常の更新ステートメントではありません。更新のロジックは何ですか?また、 'IDisposable'を実装しているオブジェクト、特に' SqlConnection'や 'SqlCommand'のようなアンマネージドリソースを扱うときには' Using'ブロックを使うべきです。 – GarethD

答えて

1

...コードです。

しかし、多分それは、各DataRowを変更し、ループの後に1バッチ内のすべての変更を送信するためにSqlDataAdapter.Update(table)を使用し、ループテーブルのRowsSqlDataAdapter.Fill(table)DataTableを埋めるために、ここで、より効率的です。 SqlDataReaderループは不要です。例えば

(未テスト):

Using con = New SqlConnection("Data Source=10.2.0.87;Initial Catalog=Inbound_Orders_DB;User ID=xxxxx;Password=xxxxxx;") 
    Using da = New SqlDataAdapter("SELECT * FROM RH_Orders where Order_DateTime is NULL ORDER by Order_Date DESC", con) 
     da.UpdateCommand = New SqlCommand("UPDATE RH_Orders SET order_DateTime = @order_DateTime WHERE ID = @Id", con) 
     da.UpdateCommand.Parameters.Add("@order_DateTime", SqlDbType.DateTime).SourceColumn = "order_DateTime" 

     Dim table = New DataTable() 
     da.Fill(table) 

     For Each row As DataRow In table.Rows 
      Dim orderDate = row.Field(Of String)("Order_Date") 
      Dim orderDateTime As DateTime 
      If DateTime.TryParse(orderDate.Substring(0, 4) & "-" & orderDate.Substring(4, 2) & "-" & orderDate.Substring(6, 2), orderDateTime) Then 
       row.SetField("order_DateTime", orderDateTime) 
      End If 
     Next 

     da.Update(table) 
    End Using 
End Using 

余談:

:代わりに "20170131" から新しい文字列 "2017年1月31日" を構築するのあなたも DateTime.TryParseExactを使用することができます
DateTime.TryParseExact("20170131", "yyyyMMdd", nothing, DateTimeStyles.None, orderDateTime) 
関連する問題