none
チェックボックスの値が、サーバーに移動反映しません。関連コードを表示します。 RRS feed

  • 質問

  • Public Sub db_dataset(ByVal n As Integer)    ’表示用
            Dim ns As Integer
          
            'SQL認証接続
            Dim St As String
            Dim Cn As New System.Data.SqlClient.SqlConnection
            Dim SQL As System.Data.SqlClient.SqlCommand
            Dim ServerName As String = "*****"   'サーバー名(またはIPアドレス)
            Dim UserID As String = "*****"      'ユーザーID
            Dim Password As String = "*****"   'パスワード
            Dim DatabaseName As String = "******"  'データソース?
            St = "Server=" & ServerName & ";"
            St &= "User ID=" & UserID & ";"
            St &= "Password=" & Password & ";"
            St &= "Initial Catalog=" & DatabaseName
            Cn.ConnectionString = St
            SQL = Cn.CreateCommand
            Cn.Open()

            Dim ds = New DataSet
            Dim sq As String
            sq = "SELECT * FROM dbo.[サーバー内のテーブル名]"
            Dim adapter = New SqlClient.SqlDataAdapter()
            adapter.SelectCommand = New SqlClient.SqlCommand(sq, Cn)
            adapter.SelectCommand.CommandType = CommandType.Text
            adapter.Fill(ds)

            Dim dt As New DataTable
            dt = ds.Tables(0)
            Me.DataGridView1.DataSource = dt
            ns = ds.Tables(0).Rows.Count
     
            Me.TX_Client_ID.Text = dt.Rows(n).Item("Client_ID").ToString
            Me.CB_CustomerType.Text = dt.Rows(n).Item("CustomerType").ToString
         
            Me.CK_FLG_Branch.Text = dt.Rows(n).Item("FLG_Branch").ToString   ←ここです!


            Cn.Close()
        End Sub


    '修正(変更)
        Private Sub TB_F3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TB_F3.Click
        
            'SQL認証接続
           ここに、前記と同じものがきます(長くなるので省略します)。
            Cn.Open()

            '修正・変更SQL
            Dim M_Client_ID As Integer
            M_Client_ID = NZ(Me.TX_Client_ID.Text)----NZは自作関数(Null値対策用)です。
            M_Client_ID = CInt(M_Client_ID)

            Dim M_CustomerType As Integer    
            M_CustomerType = NZ(Me.CB_CustomerType.Text)
            M_CustomerType = CInt(M_CustomerType)
          
            'YES/No チェックボックス
            Dim M_FLG_Branch As Boolean
            M_FLG_Branch = NZbool(Me.CK_FLG_Branch.Text) 'Yes/NO   ← ここです! NZboolは自作関数です。

            Dim SQLst As String
            SQLst = "UPDATE dbo.[サーバー内のテーブル名] SET "
            SQLst &= "CustomerType= " & M_CustomerType & ", "
          
            'Yes/No  チェックボックス 未解決
            SQLst &= "FLG_Branch= " & M_FLG_Branch & " "   '**データ型不明 YES/NO  チェックボックス   ← ここです!
         
            SQLst &= "WHERE Client_ID = " & M_Client_ID & " "
            SQL.CommandText = SQLst
            SQL.ExecuteNonQuery()

            MessageBox.Show(" ' 変更しました。 チェックボックスが、まだ変更ができない状態です(PG不備)。 研究中です! ")

            Call db_dataset(dn)
            Me.TX1.Text = dn

            Cn.Close()

        End Sub


    以下、NZ,NZbool です。
    Module Module1

        Public Function NZ(ByVal a)
            If a = "" Then
                a = 0
            ElseIf IsDBNull(a) = True Then
                a = 0
            ElseIf IsNothing(a) = True Then
                a = 0
            End If

            NZ = a
        End Function

        Public Function NZbool(ByVal a As String) As Boolean
            If a = "False" Then
                a = False
            ElseIf a = "True" Then
                a = True
            End If

            NZbool = a
        End Function
    End Module


    • 移動 山本春海 2012年4月13日 5:33 より適切と思われるカテゴリに移動しました。 (移動元:SQL Server)
    • 編集済み yksaila 2012年4月13日 9:09
    2012年4月13日 4:03

回答

  • あと文字列を結合してクエリを生成してますが、SQLインジェクション攻撃を受ける可能性があります。

    初心の方には難しいかも知れませんが、今のうちからしっかり勉強しておくことをお勧めします。以下関連スレッドです。

    http://social.msdn.microsoft.com/Forums/ja/vbgeneralja/thread/3bf2f63d-da18-4003-bd8e-656fe5698dc6

    参考までにパラメタライズドクエリを使ってコードを書き直してみました。動作は保証しませんが、何かの参考になれば幸いです。

    '修正(変更)
    Private Sub TB_F3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TB_F3.Click
    
        'SQL認証接続
        Dim ServerName As String = "*****"   'サーバー名(またはIPアドレス)
        Dim UserID As String = "*****"      'ユーザーID
        Dim Password As String = "*****"   'パスワード
        Dim DatabaseName As String = "******"  'データソース?
    
        Dim St = "Server=" & ServerName & ";"
        St &= "User ID=" & UserID & ";"
        St &= "Password=" & Password & ";"
        St &= "Initial Catalog=" & DatabaseName
    
        Using con As New System.Data.SqlClient.SqlConnection(St)
            con.Open()
    
            '修正・変更SQL
            Dim SQLst As String
            SQLst = "UPDATE dbo.[サーバー内のテーブル名] SET "
            SQLst &= "CustomerType= @CustomerType, "
            SQLst &= "FLG_Branch= @FLG_Branch "
            SQLst &= "WHERE Client_ID = @Client_ID "
    
            Dim sql As New System.Data.SqlClient.SqlCommand(SQLst, con)
            sql.Parameters.AddWithValue("@CustomerType", NZInt32(Me.CB_CustomerType.Text))
            sql.Parameters.AddWithValue("@FLG_Branch", NZBool(Me.CK_FLG_Branch.Text))
            sql.Parameters.AddWithValue("@Client_ID", NZInt32(Me.TX_Client_ID.Text))
            sql.ExecuteNonQuery()
    
            MessageBox.Show("変更しました。")
    
            Me.db_dataset(dn)
            Me.TX1.Text = dn
    
        End Using
    
    End Sub
    
    Module Module1
        Public Function NZInt32(value As String) As Int32
            Dim ret = 0
            Int32.TryParse(value, ret)
            Return ret
        End Function
    
        Public Function NZBool(value As String) As Boolean
            Dim ret = False
            Boolean.TryParse(value, ret)
            Return ret
        End Function
    End Module


    ひらぽん http://d.hatena.ne.jp/hilapon/


    2012年4月13日 5:16
    モデレータ

すべての返信

  • >SQLst &= "FLG_Branch= " & M_FLG_Branch & " "   '**データ型不明 YES/NO  チェックボックス   ← ここです!

    上記の式の結果は、

    FLG_Branch=False

    になります。この場合、SQL ServerはFLG_Branchという列に、Falseという列の値をセットしようとします。
    そうではなく、Falseという値を入れたいのであれば、以下のようにする必要があります。

    FLG_Branch='False'

    上記のようになるようにコードを修正して下さい。これでうまくいくようになりますが、実際にはSQL ServerがFalseという文字列からBit型に自動的に変換して保存してくれます。

    また、NZやNZboolという関数を作成されていますが、SQL Serverにはisnullという関数が用意されていますので、これを使えばnullの場合に返す値を指定できます。

    (追記)ご質問の内容的にはSQL Serverのスレッドというより、VBのスレッドの方が適切だと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/


    2012年4月13日 4:17
    モデレータ
  • NZBool の実装は、以下のような感じでいいと思います。

        Public Function NZbool(value As String) As Boolean
            Dim ret = False
            Boolean.TryParse(value, ret)
            Return ret
        End Function


    ひらぽん http://d.hatena.ne.jp/hilapon/


    2012年4月13日 4:45
    モデレータ
  • あと文字列を結合してクエリを生成してますが、SQLインジェクション攻撃を受ける可能性があります。

    初心の方には難しいかも知れませんが、今のうちからしっかり勉強しておくことをお勧めします。以下関連スレッドです。

    http://social.msdn.microsoft.com/Forums/ja/vbgeneralja/thread/3bf2f63d-da18-4003-bd8e-656fe5698dc6


    ひらぽん http://d.hatena.ne.jp/hilapon/

    2012年4月13日 4:54
    モデレータ
  • あと文字列を結合してクエリを生成してますが、SQLインジェクション攻撃を受ける可能性があります。

    初心の方には難しいかも知れませんが、今のうちからしっかり勉強しておくことをお勧めします。以下関連スレッドです。

    http://social.msdn.microsoft.com/Forums/ja/vbgeneralja/thread/3bf2f63d-da18-4003-bd8e-656fe5698dc6

    参考までにパラメタライズドクエリを使ってコードを書き直してみました。動作は保証しませんが、何かの参考になれば幸いです。

    '修正(変更)
    Private Sub TB_F3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TB_F3.Click
    
        'SQL認証接続
        Dim ServerName As String = "*****"   'サーバー名(またはIPアドレス)
        Dim UserID As String = "*****"      'ユーザーID
        Dim Password As String = "*****"   'パスワード
        Dim DatabaseName As String = "******"  'データソース?
    
        Dim St = "Server=" & ServerName & ";"
        St &= "User ID=" & UserID & ";"
        St &= "Password=" & Password & ";"
        St &= "Initial Catalog=" & DatabaseName
    
        Using con As New System.Data.SqlClient.SqlConnection(St)
            con.Open()
    
            '修正・変更SQL
            Dim SQLst As String
            SQLst = "UPDATE dbo.[サーバー内のテーブル名] SET "
            SQLst &= "CustomerType= @CustomerType, "
            SQLst &= "FLG_Branch= @FLG_Branch "
            SQLst &= "WHERE Client_ID = @Client_ID "
    
            Dim sql As New System.Data.SqlClient.SqlCommand(SQLst, con)
            sql.Parameters.AddWithValue("@CustomerType", NZInt32(Me.CB_CustomerType.Text))
            sql.Parameters.AddWithValue("@FLG_Branch", NZBool(Me.CK_FLG_Branch.Text))
            sql.Parameters.AddWithValue("@Client_ID", NZInt32(Me.TX_Client_ID.Text))
            sql.ExecuteNonQuery()
    
            MessageBox.Show("変更しました。")
    
            Me.db_dataset(dn)
            Me.TX1.Text = dn
    
        End Using
    
    End Sub
    
    Module Module1
        Public Function NZInt32(value As String) As Int32
            Dim ret = 0
            Int32.TryParse(value, ret)
            Return ret
        End Function
    
        Public Function NZBool(value As String) As Boolean
            Dim ret = False
            Boolean.TryParse(value, ret)
            Return ret
        End Function
    End Module


    ひらぽん http://d.hatena.ne.jp/hilapon/


    2012年4月13日 5:16
    モデレータ
  • 以下のようにして、解決しました。

    回答していただいた方全員にお送りしたいのですが、うるさくなると困りますのでここに記載します。

    皆様、ありがとうございました。 まだ、フォーラムの使い方になれていませんので(今日で4日目?)、ご迷惑をおかけしました。

    お許しください。

    以下、解決内容です(一部残っていますが、基本的には解決です)。

    1.VBのチェックボックス自体が、チェックを変更しても変わらなかったので、下記のコードを追加しました。
     もともと、そうなのか、私の設定が違っていたのかは、不明です。

        Private Sub CK_FLG_Branch_Click(sender As System.Object, e As System.EventArgs) Handles CK_FLG_Branch.Click
            If Me.CK_FLG_Branch.Text = False Then
                Me.CK_FLG_Branch.Text = True
            ElseIf Me.CK_FLG_Branch.Text = True Then
                Me.CK_FLG_Branch.Text = False
            End If
        End Sub

    2.チェックボックスのプロパティの「CheckState」を、’Checked’にしておきます。

    3.プログラムコード内の定義を以下のようにします。
         'YES/No チェックボックス
            Dim M_FLG_Branch As String ’← ’***
            M_FLG_Branch = Me.CK_FLG_Branch.Text   'Yes/NO
            M_FLG_Branch = NZbool(M_FLG_Branch)  ’自作関数:NZbool

    ’***
    理由:クライアントには、Booleanでなく、Stringとして渡しているようなので、上記のように定義しました。


    4.’Nzbool’は、自作関数です。

      Public Function NZbool(ByVal a)
            If a = "False" Then
                a = 0
            ElseIf a = "True" Then
                a = -1
            End If

            NZbool = a
        End Function

    5.SQLサーバー側では、Yes/No(Boolean)を、-1/0として扱っているので、こうしました。

    6.チェックボックスの☑が、True/Falseの表示に対応していません。(2)が、おかしいのかも?
     たぶん、チェックボックスの設定がいけないのでしょう。 
     もう少し、ここはやってみます。 わからなければ、また質問します。

    今回は、おかげさまでサーバーへの書き込みは成功しました。
    ありがとうございました。


    これで、うまくいきました。

    2012年4月13日 10:24
  • ひらぽんさんへ、

    ご教示ありがとうございました。 SQLインジェクションについても勉強しました。 まだ完全には自分のものには、なっていませんが、時間をかけて勉強します。

    コードも大変参考になりました。パラメタライズドクエリをこれから心がけます。

    さて、二点質問させてください。

    1.SQLインジェクションの件ですが、サーバーに侵入されず、クライアント側からでも攻撃できるのでしょうか(クライアントには、.EXEしか置きません)?

    クライアント側からサーバーへの侵入を相当に防御している場合も(ま、これも程度問題ですが)、危険性がありますか?

    2.先に教えていただいたコードの中: Using con As New System.Data.SqlClient.SqlConnection(St) ~ End Usingのあいだに、con.Open()があってCon.Close()がないのですが、

    かまわないのでしょうか? それとも、End Usingがあるので良いのでしょうか?

    以上です、よろしくお願いします。

    勉強を始めたばかりで的外れの発言もあるでしょうが、この点はお許しください。

    yksaila




    2012年4月14日 8:25
  • まず SQL インジェクションですが、クライアント側から入力値にクエリ文字列を設定して攻撃を行う手法です。パラメタライズドクエリを用いず、文字列の結合でクエリを生成している場合セキュリティホールとなるため、SQL インジェクション攻撃を受ける恐れが高くなりますが、SqlCommand.Parameters でパラメータを設定すると、仮にクエリを設定しても文字列として扱われるため、SQL インジェクション攻撃の回避ができます。

    http://itpro.nikkeibp.co.jp/article/MAG/20070608/274192/
    http://www.atmarkit.co.jp/fdotnet/basics/adonet03/adonet03_02.html


    次に SqlConnection の Closeですが、Using ステートメントを抜ける際、Close メソッドとDispose メソッドが呼ばれ、接続を閉じるのとオブジェクトを解放することが保証されてます。

    http://msdn.microsoft.com/ja-jp/library/system.data.sqlclient.sqlconnection(v=vs.80).aspx

    Using ステートメントの解説も読んでみてください。

    http://msdn.microsoft.com/ja-jp/library/htd05whh.aspx


    ひらぽん http://d.hatena.ne.jp/hilapon/

    2012年4月16日 1:30
    モデレータ
  • ひらぽんさんへ

    ありがとうございました。

    yksaila


    • 編集済み yksaila 2012年4月17日 1:37
    2012年4月16日 14:44