VB.NET

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
まーくん
記事: 11
登録日時: 11年前

VB.NET

#1

投稿記事 by まーくん » 11年前

前回PHPの設問をさせていただいた者です。
PHPの問題も解決はしていませんが、今回はVB.netについての質問をさせていただきます。

<問題点>
・コードの冗長化を無くしたい
自分なりに、クラスの先頭で

コード:

        Dim Cn As New OleDbConnection
としたのですが、内部でエラーになってしまいます。

そもそも、DB操作の知識が浅いせいも有りますが、「こうした方がいい」というアドバイスをいただけたら嬉しいです。

コードは以下。
DBへの追加、更新、削除などを行っています。
プリペアドステートメントも使う予定です。(今回は使う方法を探る前のコードなので使っていません。)
尚、まだこのコードは作成途中なので色々おかしい所はあります。
今回は冗長化を無くすためのアドバイスを頂きたいです。

何回もCnをNewしないようにするにはどうしたらいいでしょうか。
adapterは毎回違うものを使ったほうがいいのでしょうか?

コード:

Imports System.Data.OleDb

Public Class 定休日設定

    Dim Table As New DataTable
    Dim dr As OleDb.OleDbDataReader


    Private Sub データ入力_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Me.定休日表TableAdapter.Fill(Me.Sotuken1DataSet.定休日表)

        Dim Cn As New OleDbConnection
        Dim SQLCm As OleDbCommand = Cn.CreateCommand
        Dim Adapter As New OleDbDataAdapter(SQLCm)

        Cn.ConnectionString = ("****")
        Cn.Open()

        SQLCm.CommandText = "SELECT * FROM 定休日表"
        Adapter.Fill(Table) '実行

        dr = SQLCm.ExecuteReader

        If dr.HasRows Then
            Do While dr.Read
                list_holiday.Items.Add(dr("定休日コード").ToString & "   " & dr("年").ToString & "年" & dr("月").ToString & "月" _
                                   & dr("日").ToString & "日   " & WeekdayName(dr("曜日")))
            Loop
        Else
            MsgBox("データなし")
        End If


        '▼後処理
        Adapter.Dispose()
        Cn.Dispose()
        Cn.Close()


        lbl_fullday.Text = MonthCalendar1.SelectionStart.ToShortDateString()
        lbl_year.Text = Mid(lbl_fullday.Text, 1, 4)
        lbl_month.Text = Mid(Mid(lbl_fullday.Text, 6, 7), 1, 2)
        lbl_day.Text = Mid(lbl_fullday.Text, 9, 10)

        lbl_fulldayE.Text = MonthCalendar1.SelectionEnd.ToShortDateString()
        lbl_yearE.Text = Mid(lbl_fulldayE.Text, 1, 4)
        lbl_monthE.Text = Mid(Mid(lbl_fulldayE.Text, 6, 7), 1, 2)
        lbl_dayE.Text = Mid(lbl_fulldayE.Text, 9, 10)

        Label1.Text = WeekdayName(Weekday(DateSerial(lbl_year.Text, lbl_month.Text, lbl_day.Text)))

    End Sub




    Private Sub btn_add_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_add.Click

        Dim Cn As New OleDbConnection
        Dim SQLCm As OleDbCommand = Cn.CreateCommand
        Dim Adapter As New OleDbDataAdapter(SQLCm)
        Dim Adapter2 As New OleDbDataAdapter(SQLCm)

        Dim range As Integer = lbl_dayE.Text - lbl_day.Text '複数日選択判定用変数

        Me.定休日表TableAdapter.Fill(Me.Sotuken1DataSet.定休日表)
        Cn.ConnectionString = ("****")
        'パターン表に追加処理
        Cn.Open()

        Dim cnt As Integer = list_holiday.Items.Count + 1
        Dim weekDayN As Integer = Weekday(DateSerial(lbl_year.Text, lbl_month.Text, lbl_day.Text))

        Do While range > -1

            SQLCm.CommandText = "INSERT INTO 定休日表 ([定休日コード],[年],[月],[日],[曜日]) VALUES (" & cnt & "," & lbl_year.Text & "," & lbl_month.Text & "," & lbl_day.Text & "," & weekDayN & ")"
            Adapter.Fill(Table)
            cnt = cnt + 1
            lbl_day.Text = lbl_day.Text + 1
            range = range - 1
            weekDayN = weekDayN + 1
            If weekDayN > 7 Then
                weekDayN = 1
            End If

        Loop


        '後処理
        Adapter.Dispose()
        Cn.Dispose()
        Cn.Close()

        'パターン表再表示
        list_holiday.Items.Clear()
        Cn.ConnectionString = ("****")
        Cn.Open()
        SQLCm.CommandText = "SELECT * FROM 定休日表"
        Adapter2.Fill(Table)
        dr = SQLCm.ExecuteReader
        If dr.HasRows Then
            Do While dr.Read
                list_holiday.Items.Add(dr("定休日コード").ToString & "   " & dr("年").ToString & "年" & dr("月").ToString & "月" _
                                   & dr("日").ToString & "日   " & WeekdayName(dr("曜日")))
            Loop
        End If
        '後処理
        Adapter2.Dispose()
        Cn.Dispose()
        Cn.Close()
    End Sub

    Private Sub btn_delete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_delete.Click
        Dim Cn As New OleDbConnection
        Dim SQLCm As OleDbCommand = Cn.CreateCommand
        Dim Adapter As New OleDbDataAdapter(SQLCm)
        Dim Adapter2 As New OleDbDataAdapter(SQLCm)
        Dim Adapter3 As New OleDbDataAdapter(SQLCm)


        Me.定休日表TableAdapter.Fill(Me.Sotuken1DataSet.定休日表)
        '選択した行の削除
        Cn.ConnectionString = ("****")
        Cn.Open()

        SQLCm.CommandText = "DELETE FROM 定休日表 WHERE 定休日コード = " & list_holiday.SelectedIndex.ToString + 1

        Dim range As Integer = list_holiday.SelectedIndices.Count

        Do While range > 0

            SQLCm.CommandText = "INSERT INTO 定休日表 ([定休日コード],[年],[月],[日],[曜日]) VALUES (" & cnt & "," & lbl_year.Text & "," & lbl_month.Text & "," & lbl_day.Text & "," & weekDayN & ")"
            Adapter.Fill(Table)
            cnt = cnt + 1
            lbl_day.Text = lbl_day.Text + 1
            range = range - 1
            weekDayN = weekDayN + 1
            If weekDayN > 7 Then
                weekDayN = 1
            End If

        Loop

        Adapter.Fill(Table)

        Adapter.Dispose()
        Cn.Dispose()
        Cn.Close()


        '選択した行が一番下以外の場合繰り上げ処理を行う
        Dim i As Integer
        i = list_holiday.SelectedIndex.ToString + 1
        Cn.ConnectionString = ("****")
        Cn.Open()

        SQLCm.CommandText = "update 定休日表 set 定休日コード = 定休日コード -1 where 定休日コード > " & i
        Adapter2.Fill(Table)
        Adapter2.Dispose()
        Cn.Dispose()
        Cn.Close()

        'パターン表再表示
        list_holiday.Items.Clear()
        Cn.ConnectionString = ("****")
        Cn.Open()
        SQLCm.CommandText = "SELECT * FROM 定休日表"
        Adapter3.Fill(Table)
        dr = SQLCm.ExecuteReader
        If dr.HasRows Then
            Do While dr.Read
                list_holiday.Items.Add(dr("定休日コード").ToString & "   " & dr("年").ToString & "年" & dr("月").ToString & "月" _
                                   & dr("日").ToString & "日   " & WeekdayName(dr("曜日")))
            Loop
        End If
        '後処理
        Adapter3.Dispose()
        Cn.Dispose()
        Cn.Close()
    End Sub

    Private Sub weekend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_weekend.Click

        '土日を判定し、休み登録

        Dim today As Date = DateTime.Today
        Dim cnt As Integer = list_holiday.Items.Count + 1
        Dim firstOfMonth As Date = DateSerial(lbl_year.Text, lbl_month.Text, 1) '月初
        Dim endOfMonth As Date = DateSerial(lbl_year.Text, lbl_month.Text + 1, 0) '月末
        'MsgBox(WeekdayName(endOfMonth))

        If Weekday(firstOfMonth) = 7 Then '土曜日

            For i As Integer = firstOfMonth.Day To endOfMonth.Day

            Next

        ElseIf Weekday(firstOfMonth) = 1 Then '日曜日

        Else 'その他

        End If
    End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.Close()
    End Sub

    Private Sub 定休日表BindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Me.Validate()
        Me.定休日表BindingSource.EndEdit()
        Me.TableAdapterManager.UpdateAll(Me.Sotuken1DataSet)

    End Sub

    Private Sub MonthCalendar1_DateChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DateRangeEventArgs) Handles MonthCalendar1.DateChanged

        lbl_fullday.Text = MonthCalendar1.SelectionStart.ToShortDateString()
        lbl_year.Text = Mid(lbl_fullday.Text, 1, 4)
        lbl_month.Text = Mid(Mid(lbl_fullday.Text, 6, 7), 1, 2)
        lbl_day.Text = Mid(lbl_fullday.Text, 9, 10)

        lbl_fulldayE.Text = MonthCalendar1.SelectionEnd.ToShortDateString()
        lbl_yearE.Text = Mid(lbl_fulldayE.Text, 1, 4)
        lbl_monthE.Text = Mid(Mid(lbl_fulldayE.Text, 6, 7), 1, 2)
        lbl_dayE.Text = Mid(lbl_fulldayE.Text, 9, 10)

        Label1.Text = WeekdayName(Weekday(DateSerial(lbl_year.Text, lbl_month.Text, lbl_day.Text)))





    End Sub
End Class

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: VB.NET

#2

投稿記事 by softya(ソフト屋) » 11年前

VBはさっぱりですが、Classのメンバでnewしたらいけないのですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

まーくん
記事: 11
登録日時: 11年前

Re: VB.NET

#3

投稿記事 by まーくん » 11年前

返信有難うございます。

Newするのは全然構わないのですが、そのNEWする回数も多いし、同じnewしてばかりなのです。

その回数を減らしたり、冗長コードを無くしたいです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: VB.NET

#4

投稿記事 by softya(ソフト屋) » 11年前

まーくん さんが書きました:返信有難うございます。

Newするのは全然構わないのですが、そのNEWする回数も多いし、同じnewしてばかりなのです。

その回数を減らしたり、冗長コードを無くしたいです。
メンバ関数ローカルではなく、classのメンバにするって話なのですが。
それならclassのインスタンス生成時だけなのでは?

※ VB用語がわかりませんせんが関数ではなくサブルーチンかな? メソッドとも呼ばなさそうだし。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: VB.NET

#5

投稿記事 by YuO » 11年前

まーくん さんが書きました:・コードの冗長化を無くしたい
これだけであれば,単純にConnection作成用のモジュールを用意するだけでよいかと思います。
データベースはモデルが取り扱うので,モデルの中でうまいこと取り回すことも多いですが……。

ただ,全体的に見るといくつか……。
  • Disposeを明示で呼び出すのでは無く,Usingブロックを使います。
    データベースへのアクセスは例外が発生するもの,という前提で対処すべきです。
    現在のコードでは,例外が発生するとコネクションがGCされるまで閉じられません。
  • メソッド内で同一の接続先へのコネクションを作って潰すのは,特別な理由が無い斬り無駄です。
    コネクションプーリングがあるとはいえ,Newは時間がかかる作業です。
    このため,メソッドの最初で作って最後までUsingブロックに入れてしまいます。
    また,Adapterも使い回すことができます。
  • フィールドにコネクションを持つのは危険です。
    ASP.NETでは応答時間が短いため,リクエストの開始から終了まで接続し続ける実装もありですが,WinFormsでは無意味に長い時間接続を保持し続けることになってしまいます。
    メソッド単位で開いて閉じるのがよいでしょう (メソッドの状況によっては,引数としてもらうのもよいでしょう)。

まーくん
記事: 11
登録日時: 11年前

Re: VB.NET

#6

投稿記事 by まーくん » 11年前

softya(ソフト屋) さんが書きました:
まーくん さんが書きました:返信有難うございます。

Newするのは全然構わないのですが、そのNEWする回数も多いし、同じnewしてばかりなのです。

その回数を減らしたり、冗長コードを無くしたいです。
メンバ関数ローカルではなく、classのメンバにするって話なのですが。
それならclassのインスタンス生成時だけなのでは?

※ VB用語がわかりませんせんが関数ではなくサブルーチンかな? メソッドとも呼ばなさそうだし。
理解が浅く申し訳ありません。
ローカルではなくメンバにするというのは何度かやりました。
ですが、エラーが出てしまい実行不可能です。

ごめんなさい、今実行できる環境下ではないので、また改めてエラーに関してはメモしておきます。

まーくん
記事: 11
登録日時: 11年前

Re: VB.NET

#7

投稿記事 by まーくん » 11年前

YuO さんが書きました:
まーくん さんが書きました:・コードの冗長化を無くしたい
これだけであれば,単純にConnection作成用のモジュールを用意するだけでよいかと思います。
データベースはモデルが取り扱うので,モデルの中でうまいこと取り回すことも多いですが……。

ただ,全体的に見るといくつか……。
  • Disposeを明示で呼び出すのでは無く,Usingブロックを使います。
    データベースへのアクセスは例外が発生するもの,という前提で対処すべきです。
    現在のコードでは,例外が発生するとコネクションがGCされるまで閉じられません。
  • メソッド内で同一の接続先へのコネクションを作って潰すのは,特別な理由が無い斬り無駄です。
    コネクションプーリングがあるとはいえ,Newは時間がかかる作業です。
    このため,メソッドの最初で作って最後までUsingブロックに入れてしまいます。
    また,Adapterも使い回すことができます。
  • フィールドにコネクションを持つのは危険です。
    ASP.NETでは応答時間が短いため,リクエストの開始から終了まで接続し続ける実装もありですが,WinFormsでは無意味に長い時間接続を保持し続けることになってしまいます。
    メソッド単位で開いて閉じるのがよいでしょう (メソッドの状況によっては,引数としてもらうのもよいでしょう)。
返信有難うございます!
モジュール、ですか。
以前挑戦したことが会ったのですが、標準モジュールに入れると上手く動作しないので諦めたのです。また挑戦して、エラーが出たら改めて報告させていただきます。
随時調べながら対処はします。

Usingはサンプルコードでよく見かけますね…。次に実行環境に移れるのが火曜日になってしまうので、改めて挑戦します。ありがとうございます。

Adapter使いまわしできるというのは驚きました。私もなんとか使いまわせないものかと挑戦していたのですが"adapter.fill"のエラーが頻繁に起きてしまい断念してしまいましました。またエラーについてはまとめておきます。

メソッド単位でコネクションを開閉するのは考えてはいますが、私の知識不足でどうもエラーが起きてしまいます…。
こちらもごめんなさい、明確なエラー名はメモしておくのをわすれました。


折角返答いただいたのに此方の準備不足で申し訳ないです。

次に活かして頑張ります、また改めて相談させていただきます。

閉鎖

“C言語何でも質問掲示板” へ戻る