DOBON.NETプログラミング道掲示板

■ 「新規作成」から投稿できます。
■ マルチポストされた投稿を見つけたときは、その投稿に返信することによりご報告ください。その際は匿名で投稿し、マルチポストされている場所を併記してください。
■ スパム対策のため、メールアドレスの先頭に"_"という文字が付加されています。
RSS 2.0 RSS 2.0 | RSS 0.91 | 携帯電話用 | 自分専用のアイコンを使用するには | 掲示板への要望 | 管理人に連絡 | お気楽掲示板
■ 24時間以内に作成されたスレッドは New で表示されます。
■ 24時間以内に更新されたスレッドは UpDate で表示されます。

記事リスト ( )内の数字はレス数
Nomal参照dllへの文字列引数をutf8で渡したい。(13) | NomalFILE.COPYでIOExceptionエラーが出る(11) | Nomalリストを別フォームに渡す方法(9) | Nomal例外発生した場合に変数をcatchに渡したい(9) | NomalCode128でバーコードが読み取れない(8) | Nomalモードレスフォーム Warning IDE0067を回避したい(7) | NomalIE11では表示されるが、.netのWebBrowserでは、表示されないHPを表示する方法(7) | Nomal数字だけで構成されてるCSVフィールドが自動的に数値として解釈される(7) | NomalフォームコントロールへのDataBindingsでプロパティが相互反映されない(7) | Nomal起動ディスプレイの指定方法について(6) | NomalListBoxにデータが表示されない(6) | Nomal文字列を8bit に戻してから UTF-8 に変換する方法(6) | NomalSQLServerテーブル内容をDataGridViewに表示するコードについて(6) | Nomal文字列構造体のListのソート(6) | NomalWebBrowser Controlを使って、任意の値を取得(5) | Nomalこんな演算子初めて見ました。(5) | NomalRichTextBoxで入力文字の自動折り返しを止めたい(5) | NomalあるWindows10PCでビルドしたEXEがW8.1以下で実行エラー(5) | Nomalポルトガル語の登録(5) | Nomaloo4oのAddTableをADOに移行したい(5) | NomalDeclare宣言するdllと参照追加をするdllの区別(4) | NomalVS2017で作成されたDLLをVS2005で作成されたAPで使用する方法(4) | Nomalフォルダ内の全ての容量を取得したい(4) | Nomal共変性と反変性ってこういうこと?(4) | Nomalプロセスからウインドウを取得(4) | NomalNewの使い方間違ってますか?(4) | Nomalユーザーコントロール内のテキストボックスのmodifiedプロパティ(4) | NomalJOIN操作の構文エラー(4) | Nomal動的にプロパティや変数の値の取得(4) | NomalVB6 ほかのアプリケーションを起動し そのアプリケーションは終了させる方法(4) | Nomalスクロールバーが出た時に高さを変えたい(4) | NomalDatagridViewの行高さ変更について(4) | NomalLINQのメソッド構文の書き方(3) | Nomalvb.net+SQLiteで複数データベースファイルへのトランザクション方法(3) | Nomalジェネリック型インターフェースを使った変数を扱いたい(3) | NomalProcess.WaitForExitで正常に動作しない?(3) | NomalPictureBox.Locationのキャンセル(3) | NomalCatch時のex.StackTraceの情報(3) | NomalVisualStudioでマクロ(3) | NomalOracleDataAccess を参照したプログラムでデバッグモードが機能しなくなる(3) | NomalVisualStudioでExcelのVSTO開発(3) | NomalVB.NETでCSVを読み込む際にSQL文を使いたい(3) | NomalDrawImage でメモリ不足エラー(3) | NomalVb.netからAccessへの接続について(3) | Nomal令和の日付への対応(3) | NomalHTTP 417エラーを発生させるためのIIS設定はどうすればよいか(3) | NomalDrawString前のFillRectangle有無により文字の太さが違う理由について教えて下さい(3) | NomalPIctureBox同士を論理合成したい(3) | Nomalデータセット定義ファイルからDataTable(3) | Nomalネットの画像の複数枚を重ね合わせたい(3) | NomalDataGridViewで検索をかける方法(3) | NomalDataGridViewの選択時の色を透明にしたい(3) | NomalWebBrowserでWebページからのメッセージ(3) | NomalASP.NETから呼ばれているかどうか判定する方法(3) | NomalCA2213の警告が消えません(3) | NomalC# 現在のコンテキスト内にxxxという文字は存在しませんと出ます(3) | NomalTaskクラスを.NET Framework 2.0で実現させる方法(2) | NomalWebBrowser Control foreachで値が消える(2) | NomalEditボックスに簡体字をセットする方法(2) | NomalWebClientが上手く動かない(2) | Nomalフォーム外のカーソルの変更(2) | Nomalラムダ式の勉強中(2) | NomalRichTextBoxで入力文字の自動折り返しを止めたい(2) | NomalC#をVBに変換(2) | NomalWebClientで、短期間にDownloadStringAsyncを実行したい(2) | NomalマウスのないOSでマウスカーソルの表示(2) | NomalToolStripMenuItemにShortcutKeysを指定した際の、元のコントロールを取得する方法(2) | NomalMouseEventArgsのカレント座標(2) | Nomalリッチテキストボックスでの字間の調整(2) | NomalVC++ → VB.Netに変換時に文法エラー(2) | NomalSQL-Server Compact 4.0が表示されない(2) | Nomalバーコードの数字を非表示にしたい(2) | Nomal自作したアプリの発行元を明記したい(2) | NomalSystem.Threading.Thread.Sleep()と変数(2) | NomalDataGridView 行の背景色の設定(2) | NomalDatagridviewのクリア(2) | NomalnumericUpDwonコントロールのvalue(2) | NomalVisual Studio DataTableの値のアクセスの仕方(2) | NomalDataTableの構造が同じか調べるメソッド(2) | NomalRejectChangesについて(2) | NomalPC機種によってスタートアップ画面が中央から左上にずれる、Fontがおかしくなる。(2) | Nomalタスクスケジュール登録時の例外メッセージ(2) | Nomal管理者モードでクリック(2) | NomalVB2017でのインストーラ作成時のエラーについて(2) | NomalMicrosoft Azure OCRのサンプルコード実行時エラー(2) | Nomalデータバインド時のDataGridViewのカスタムソート(2) | NomalObject型からDecimalへの変換(2) | Nomal擬似言語をVBのプログラミングに変換(2) | Nomalユーザーコントロールのプロパティが保存されない(2) | NomalWindows10(1803)からGetHostEntryでipv4が取得出来ない場合がある(2) | Nomal自分自身を呼び出すのはOKですか(1) | NomalList型でエラーが起きてしまい・・・(1) | NomalLINQの拡張メソッドの定義(1) | NomalWebRequest でメモリが解放されない(1) | NomalFunction プロシージャからの文字選択(1) | NomalRDP接続でのネットワーク帯域制限(0) | Nomal必須コンポーネントの一覧に追加したい(0) | NomalApp.configのMy.Application.Log設定で使用できない属性が出る(0) | Nomalvb2010を使用したmicrosoft Wordの任意の行の削除(0) | NomalWinFormsでWindows10のカメラアプリと連携したい(0) |



■記事リスト / ▼下のスレッド
■34219 / 親記事)  スクロールバーが出た時に高さを変えたい
□投稿者/ 猫まっしぐら 一般人(12回)-(2019/04/12(Fri) 01:07:58)
  • アイコン環境/言語:[Windows7 VB.net2005 WinForms] 
    分類:[.NET] 

    いつもお世話になっております
    AutoScroll=True,WrapContents=FalseなFlowLayoutPanelにボタンをずらっと並べています
    このパネルが幅を変更されてボタンが表示出来なくなった時にスクロールバーが表示されるのはいいのですが、スクロールバーがボタンに被さって表示されてしまいます
    かと言ってスクロールバーの高さを予め余分に取っておくとスクロールバーが表示されない時に間が抜けて見えてしまいます
    スクロールバーが表示されない時はパネルがボタンの高さで、表示されたらスクロールバーの高さ分自動的にパネルの高さを高くしたいのですが、そんなことは可能でしょうか
    よろしくお願いします
違反を報告
引用返信

▽[全レス4件(ResNo.1-4 表示)]
■34221 / ResNo.1)  Re[1]: スクロールバーが出た時に高さを変えたい
□投稿者/ Hongliang 大御所(556回)-(2019/04/12(Fri) 09:21:56)
  • アイコン.SizeChangedイベントにて、.HorizontalScroll.Visibleをチェックして、それによって.Heightを切り替える、というのはどうでしょう。
    横スクロールバーの高さはSystemInformation.HorizontalScrollBarHeightで取得できます。
違反を報告
引用返信
■34222 / ResNo.2)  Re[2]: スクロールバーが出た時に高さを変えたい
□投稿者/ Hongliang 大御所(557回)-(2019/04/12(Fri) 09:56:35)
  • アイコン追記。
    横スクロールバーが付くギリギリのところで縦スクロールバーが一瞬出たりしてちょっと目障りな感じ。
    イベントハンドラの最後で.PerformLayout()すれば縦スクロールバーを防げるっぽい。
違反を報告
引用返信
■34223 / ResNo.3)  Re[2]: スクロールバーが出た時に高さを変えたい
□投稿者/ 猫まっしぐら 一般人(13回)-(2019/04/12(Fri) 11:05:52)
  • アイコンNo34221に返信(Hongliangさんの記事)

    レスありがとうございます

    > .SizeChangedイベントにて、.HorizontalScroll.Visibleをチェックして、それによって.Heightを切り替える、というのはどうでしょう。

    これで出来ました
    ありがとうございました
解決み!
違反を報告
引用返信
■34224 / ResNo.4)  Re[3]: スクロールバーが出た時に高さを変えたい
□投稿者/ 猫まっしぐら 一般人(14回)-(2019/04/12(Fri) 11:09:56)
  • アイコンNo34222に返信(Hongliangさんの記事)

    入れ違いになってしまいました(^^;

    > 追記。
    > 横スクロールバーが付くギリギリのところで縦スクロールバーが一瞬出たりしてちょっと目障りな感じ。
    > イベントハンドラの最後で.PerformLayout()すれば縦スクロールバーを防げるっぽい。

    私もこれ出たり出なかったりでちょっと迷いましたが1ピクセル余分にしたら出なくなりました
    重ねてありがとうございました
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-4]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■34073 / 親記事)  DatagridViewの行高さ変更について
□投稿者/ haru 一般人(1回)-(2018/12/23(Sun) 16:18:50)
  • アイコン環境/言語:[Windows10 VB2005] 
    分類:[.NET] 

    2018/12/23(Sun) 16:38:54 編集(投稿者)
    2018/12/23(Sun) 16:38:47 編集(投稿者)

    VB2005で開発しています。

    ユーザーがマウスで変えた行高さを他の行に反映するのは

    dim wkHeight as integer = ユーザーが変更した行の高さ

    for ix as integer = 0 to dgv.rows.count - 1
    dgv.rows(idx).height = wkHeight
    next ix

    この方法だと、rowheightchangedイベントに記載しているので
    表示されている行数分イベントが走り、とても遅くなります。


    なにかいい方法はありませんか?

違反を報告
引用返信

▽[全レス4件(ResNo.1-4 表示)]
■34074 / ResNo.1)  Re[1]: DatagridViewの行高さ変更について
□投稿者/ Hongliang 大御所(546回)-(2018/12/23(Sun) 16:55:25)
  • アイコン// さすがにVS2005はちょっと古すぎるのでは…。

    ・メンバ変数m_UserRowHeight(仮名)を定義、初期値は-1とする
    ・RowHeightInfoPushedイベントで、m_UserRowHeightにe.Heightを代入してDataGridView1.Invalidate()
    ・RowHeightInfoNeededイベントで、m_UserRowHeightが-1でなければe.Heightにm_UserRowHeightを代入

    というのはどうでしょうか。
違反を報告
引用返信
■34075 / ResNo.2)  Re[2]: DatagridViewの行高さ変更について
□投稿者/ haru 一般人(3回)-(2018/12/23(Sun) 18:00:17)
  • アイコン2005古いですよね・・・・そこは目をつむってください💦

    virtualmodeをtrueにしたらセルの値が何も表示されなくなってしまいました。
    うちの今の作り方では使えないかも。。。
    あ、datasouceも使ってないです。
違反を報告
引用返信
■34076 / ResNo.3)  Re[3]: DatagridViewの行高さ変更について
□投稿者/ 魔界の仮面弁士 大御所(1184回)-(2018/12/25(Tue) 11:36:41)
  • アイコン
    2018/12/26(Wed) 01:34:25 編集(管理者)
    
    ■No34073に返信(haruさんの記事)
    > for ix as integer = 0 to dgv.rows.count - 1
    > dgv.rows(idx).height = wkHeight
    ix ≠ idx ですね…?
    
    
    ■No34075に返信(haruさんの記事)
    > 💦
    「汗」の絵文字ですね。
    https://www.fileformat.info/info/unicode/char/1f4a6/index.htm
    
    
    > virtualmodeをtrueにしたらセルの値が何も表示されなくなってしまいました。
    仮想モードを有効にする(VirtualMode = True)ということは、
     各種の通知イベントに応答してデータを渡す
    というコーディングが必要であることを意味します。
    https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/controls/implementing-virtual-mode-wf-datagridview-control
    
    
    
    > あ、datasouceも使ってないです。
    DataGridView を扱う場合、Rows コレクションを For / For Each で反復処理したり
    Rows.Add したりすることは極力避けるべきです。
    
    DataSource プロパティに BindingList や DataTable を割り当てて使用することは
    パフォーマンス改善にも大きな効果がありますので、是非検討してみてください。
    
    
    以下実験コード。
    空の Form1 に貼って試してみてください。
    
    20列×8192行の DataGridView が 2 つ表示されますが、
    左グリッド(dgv1)は haru さんの No34073 案で高さを変更したもの
    右グリッド(dgv2)は Hongliang さんの No34074 案で高さを変更したものです。
    
    
    Public Class Form1
        Private WithEvents sp As SplitContainer
        Private WithEvents dgv1 As DataGridView
        Private WithEvents dgv2 As DataGridView
        Private dummyRows As System.ComponentModel.BindingList(Of Object)
        Private userRowHeight As Integer = -1
    
        Public Sub New()
            Const InitialCowCount As Integer = 20
            Const InitialRowCount As Integer = 8192
    
            InitializeComponent()
    
            sp = New SplitContainer()
            sp.Dock = DockStyle.Fill
            Controls.Add(sp)
    
            dgv1 = New DataGridView()
            dgv2 = New DataGridView()
            dgv1.Dock = DockStyle.Fill
            dgv2.Dock = DockStyle.Fill
            dgv1.ColumnCount = InitialCowCount
            dgv2.ColumnCount = InitialCowCount
    
            dgv1.RowCount = InitialRowCount
    
            'dgv2.RowCount = InitialRowCount
            dummyRows = New System.ComponentModel.BindingList(Of Object)(New List(Of Object)(New Object(InitialRowCount - 1) {}))
            dgv2.DataSource = dummyRows
    
            dgv1.Parent = sp.Panel1
            dgv2.Parent = sp.Panel2
            dgv2.AllowUserToAddRows = True
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            sp.SplitterDistance = ClientSize.Width \ 2
        End Sub
    
        Private Sub dgv1_RowHeightChanged(sender As Object, e As DataGridViewRowEventArgs) Handles dgv1.RowHeightChanged
            Dim dgv As DataGridView = DirectCast(sender, DataGridView)
            Dim rows As DataGridViewRowCollection = dgv.Rows
            RemoveHandler dgv.RowHeightChanged, AddressOf dgv1_RowHeightChanged
    
            'ユーザーが変更した行の高さ
            Dim wkHeight As Integer = e.Row.Height
    
            For ix As Integer = rows.Count - 1 To 0 Step -1
                rows(ix).Height = wkHeight
            Next ix
    
            AddHandler dgv.RowHeightChanged, AddressOf dgv1_RowHeightChanged
        End Sub
        Private Sub dgv2_RowHeightInfoPushed(sender As Object, e As DataGridViewRowHeightInfoPushedEventArgs) Handles dgv2.RowHeightInfoPushed
            userRowHeight = e.Height
            DirectCast(sender, DataGridView).Invalidate()
        End Sub
        Private Sub dgv2_RowHeightInfoNeeded(sender As Object, e As DataGridViewRowHeightInfoNeededEventArgs) Handles dgv2.RowHeightInfoNeeded
            If userRowHeight <> -1 Then
                e.Height = userRowHeight
            End If
        End Sub
    End Class
    
    
    
    併せて、Visual Studio 付属の MSDN ライブラリのチューニングに関する項もご覧ください。
    
    [開発ツールと開発言語]
    └[Visual Studio]
     └[Windows ベースのアプリケーション、コンポーネント、サービス]
      └[Windows ベースのアプリケーションの作成]
       └[Windows フォーム]
        └[Windows フォームについて]
         └[Windows フォーム コントロール]
          └[Windows フォームで使用するコントロール]
           └[DataGridView コントロール]
            └[[Windows フォーム DataGridView コントロールでのパフォーマンス チューニング]
             └[Windows フォーム DataGridView コントロールを拡張するための推奨される手順]

違反を報告
引用返信
■34078 / ResNo.4)  Re[4]: DatagridViewの行高さ変更について
□投稿者/ haru 一般人(5回)-(2018/12/25(Tue) 18:42:34)
  • アイコンHongliang 大御所さんも魔界の仮面弁士cさん。ありがとうございます。

    もう出来上がっているものなので勝手にあまり大幅には修正できないんですが、速度の遅さも問題になっているので一度提案してみます。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-4]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■34383 / 親記事)  LINQのメソッド構文の書き方
□投稿者/ VBはじめました 一般人(20回)-(2019/11/13(Wed) 13:35:31)
  • アイコン環境/言語:[VisualStudil VB.net] 
    分類:[.NET] 

    LINQのクエリ構文をメソッド構文に書き換えている時にわからなくなりました。
    詳しい方教えてください。
    (質問1)
    コメントの@-1をメソッド構文に変換すると、@-2ポクなると思いますが、
    エラーがでます。
    
    (質問2)
    コメントのA-1をメソッド構文に変換すると、A-2ポクなると思いますが、
    エラーがでます。
    
      Sub Test1()
            Dim animals = New String() {"イヌ", "ヒツジ", "ウマ", "シロナガスクジラ", "コウモリ"}
            Dim results = From name In animals Select AnimalName = name, NameLength = name.Length '@-1
            '結果セットを取得して表示
            For Each animal In results
                ListBox1.Items.Add(animal.AnimalName)
                ListBox1.Items.Add(animal.NameLength)
            Next
            Dim results1 = animals.Select(Function(animal) AnimalName = Name, NameLength = Name.Length) '@-2
            ' この引数の数を受け付ける '[Select]' がないため、オーバーロードの解決に失敗しました。
            'NameLength' は宣言されていません。アクセスできない保護レベルになっています。
        End Sub
        Sub Test2()
            Dim fileName = New StackFrame(True).GetFileName
            Dim lines = IO.File.ReadAllLines(fileName)
            Dim query = From line In lines
                        Select trimed = line.Trim
                        Where trimed.StartsWith("Dim ") AndAlso trimed.Contains("=") 'A-1
            ListBox1.Items.AddRange(query.ToArray)
            Dim query1 = lines.
                           Select(Function(line) trimed = line.Trim).
                                   Where(Function(line) trimed.StartsWith("Dim ") AndAlso trimed.Contains("=")) 'A-2
            'trimed' は宣言されていません。アクセスできない保護レベルになっています。
    
        End Sub
    
    宜しくお願いいたします。

違反を報告
引用返信

▽[全レス3件(ResNo.1-3 表示)]
■34384 / ResNo.1)  Re[1]: LINQのメソッド構文の書き方
□投稿者/ Hongliang 大御所(571回)-(2019/11/13(Wed) 13:59:26)
  • アイコンクエリ構文内のSelectの記述は、通常のVB文法における匿名型となります。
    VB 匿名型
    などでまず検索してみてください。
違反を報告
引用返信
■34387 / ResNo.2)  Re[1]: LINQのメソッド構文の書き方
□投稿者/ 魔界の仮面弁士 大御所(1258回)-(2019/11/13(Wed) 15:33:51)
  • アイコン
    No34383に返信(VBはじめましたさんの記事)
    > (質問1)
    > Dim results = From name In animals Select AnimalName = name, NameLength = name.Length '@-1
    
    クエリ構文 の Select 句にはメンバーが複数あるため、
    上記の results は、それらのメンバーを束ねた匿名型を列挙した
    「IEnumerable(Of 匿名型)」として扱われます。
    
    
    > Dim results1 = animals.Select(Function(animal) AnimalName = Name, NameLength = Name.Length) '@-2
    
    匿名型の宣言には New With { 〜 } を使います。
    ラムダ式の引数名は任意ですが、先のクエリ構文に合わせる場合、
    引数名は animal ではなく name となるでしょう。
    
    Dim results1 = animals.Select(Function(name) New With { Key .AnimalName = name, Key .NameLength = name.Length })
    
    
    このとき、匿名型のメンバーの前にある Key を外して宣言することもできます。
    
    Dim results2 = animals.Select(Function(animal) New With { Key .AnimalName = Name, .NameLength = Name.Length })
    Dim results3 = animals.Select(Function(animal) New With { .AnimalName = Name, .NameLength = Name.Length })
    
    
    results1〜3 の結果はほぼ同じように見えますが、意味は少し変わります。
    匿名型において、Key の無いメンバーは読み書き可能なプロパティとなるのに対し、
    Key をつけた項目は読み取り専用となるためです。
    
    Key メンバーは、2 つの匿名型インスタンスを Equals メソッドで比較する際に、
    両者のインスタンスが等しいかどうかを検査するための項目としても使われます。
    
    
    
    > (質問2)
    > Dim query = From line In lines
    >             Select trimed = line.Trim
    >             Where trimed.StartsWith("Dim ") AndAlso trimed.Contains("=") 'A-1
    
    質問1とは異なり、クエリ構文 の Select 句にメンバーが一つしか無いため、
    変数 query の型は「IEnumerable(Of 匿名型)」になりません。上記の query は、
    trimed の型である String を列挙するための「IEnumerable(Of String)」となります。
    
    
    
    > Dim query1 = lines.
    >                Select(Function(line) trimed = line.Trim).
    >                        Where(Function(line) trimed.StartsWith("Dim ") AndAlso trimed.Contains("=")) 'A-2
    
    質問1を真似て、匿名型で表現した場合は
       Dim query0 = lines.Select(Function(line) New With {Key .trimed = line.Trim()}) _
                         .Where(Function(o) o.trimed.StartsWith("Dim ") AndAlso o.trimed.Contains("="))
    と書けるのですが、これだと結果が「IEnumerable(Of 匿名型)」になってしまいます。
    
    今回は「IEnumerable(Of String)」で返す必要がありますので、ラムダ式は匿名型ではなく
    String を戻り値とするように記述します。
    
      Dim query1 = lines.Select(Function(line) line.Trim()) _
                        .Where(Function(trimed) trimed.StartsWith("Dim ") AndAlso trimed.Contains("="))

違反を報告
引用返信
■34388 / ResNo.3)  Re[2]: LINQのメソッド構文の書き方
□投稿者/ VBはじめました 一般人(21回)-(2019/11/14(Thu) 09:21:39)
  • アイコン魔界の仮面弁士さん

    いつも有難う御座います。
    New With {}については、前回教えて頂いたので、何度も書き込んでみたのですが、
    うまく来ませんでした。
    再び、魔界さんのコードを見て"."が抜けていたのに気づきました。
    しかし、本質が理解てきていないので、エラー文から解決に至ることができず、
    また、お手を煩わせることになりすみません。

    また、理解できていない部分が明確になり大変たすかりました。

    色々、ググってから質問しておりますが、ググればググるほど、知らない単語が出てきます。また、一つの単語を理解するだけでは、問題が解決せず、複雑に関連しておりなかなか理解が進みません。
    デリゲート、ラムダ式、式ツリー、インターフェース、匿名、型推測、クエリ構文、メソッド構文挙げれば切がありません。
    これからも、頑張って研鑽して行こうと考えています。
    また、行き詰ったときは、教えてください。
    いつも、有難う御座います。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-3]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■34365 / 親記事)  vb.net+SQLiteで複数データベースファイルへのトランザクション方法
□投稿者/ アルファアンドベータ 一般人(1回)-(2019/11/05(Tue) 22:45:15)
  • アイコン環境/言語:[VB.NET(Framework 4.6.1)] 
    分類:[.NET] 

    VB.netとSQLiteでテキストから読み込んだデータを
    複数のデータベースファイルへ(今回は2つのファイル)
    D:\test\NameTime.sqlite3
    D:\test\NameCount.sqlite3

    トランザクション処理を実施したいのですが、Commit段階で
    「the Connecion was closed and re-opened....」と
    エラーがはかれてしまいます。(実際にはinsertできている状態)
    ロールバックもわざと実施しましたがロールバックできません。

    私の書き方が悪いためトランザクションが機能していないようです。

    複数のデータベースファイルへの
    トランザクションの張り方を教えていただきたく
    こちらへ書き込みました
    よろしくお願い致します。

    開発環境
    =====================================
    IDE:VisualStdio Express 2017
    フレームワーク:NET Framework 4.6.1
    データベース:SQLite 3 NuGetパッケージ使用
           (System.Data.SQLite.Core v1.0.112)
    PC:Windows10 Pro 64bit

    本来の仕様
    @あるフォルダ内のtxtファイルからデータ読み込み
     (更新日時順にソートし読み込み)
    Aデータベース登録(トランザクションコミット前状態)
    B登録後バックアップフォルダにtxt移動
    C移動が完了したらコミット
    Dコミットが成功したら終了 
     失敗ならバックアップフォルダから戻し次のループで読み込む
    =====================================


    mainフォーム
    =====================================
    Private Sub データ登録()

    Dim strSQLite As New strSQLiteClass
    Dim SQLiteCN As New System.Data.SQLite.SQLiteConnection
    Dim tran As System.Data.SQLite.SQLiteTransaction = Nothing
    Dim Names As String
    Dim Times As String
    Dim Counts As Long
    Dim SQLiteOutFolder As String

    'DB保存先
    SQLiteOutFolder = "D:\test"

    '接続設定
    SQLiteCN.ConnectionString = "Version=3;Data Source=" & strDBFilePath & ";New=False;Compress=True;"

    'SQLiteコネクションオープン
        'これがないと.BeginTransactionでエラー
    SQLiteCN.Open()
    SQLiteCN.Close()

    tran = SQLiteCN.BeginTransaction()
    Try

          '本来であればフォルダ内のtxtファイルを
          'ループさせながら取得登録します。
    Names = "Aさん"
    Times = "00:01:20.01"
    Counts = 10


    If strSQLite.NameTime登録(SQLiteCN, Names, Times, SQLiteOutFolder) = True Then
    Else
    GoTo ErrEnd
    End If

    If strSQLite.NameCount登録(SQLiteCN, Names, Counts, SQLiteOutFolder) = True Then
    Else
    GoTo ErrEnd
    End If

    tran.Commit()


    ErrEnd:
    '正常終了しない、ErrEndの場合はロールバック
    tran.Rollback()


    Catch ex As Exception
    tran.Rollback()

    Finally
    '破棄
    tran.Dispose()
    SQLiteCN.Dispose()


    End Try


    End Sub

    =====================================



    実際に書き込むclass
    =====================================
    Public Class strSQLiteClass
    Friend Function NameTime登録(ByRef SQLiteCN As System.Data.SQLite.SQLiteConnection, ByVal Names As String, ByVal Times As String, ByVal SQLiteOutFolder As String) As Boolean


    Dim strDBFilePath As String = SQLiteOutFolder & "\NameTime.sqlite3"
    'データベースファイルの確認
    If System.IO.File.Exists(strDBFilePath) = True Then
    Else
    '存在しない
    MessageBox.Show("データベース接続エラー", "データベースが存在しません", MessageBoxButtons.OK, MessageBoxIcon.Error)
    NameTime登録 = False
    Exit Function
    End
    End If


    '接続設定
    SQLiteCN.ConnectionString = "Version=3;Data Source=" & strDBFilePath & ";New=False;Compress=True;"
    'SQLiteコネクションオープン
    SQLiteCN.Open()
    Try
    Dim SQLiteCommand As System.Data.SQLite.SQLiteCommand
    'SQLコマンド設定
    SQLiteCommand = SQLiteCN.CreateCommand
    Try


    '登録
    SQLiteCommand.CommandText = "INSERT INTO [T_NameTime] " &
    "(" &
    "Name, " &
    "Time" &
    ") " &
    "VALUES(" &
    "'" & Names & "', " &
    "'" & Times & "'" &
    ") "
    SQLiteCommand.ExecuteNonQuery()
    NameTime登録 = True

    Catch ex2 As Exception
    MessageBox.Show(ex2.Message)
    NameTime登録 = False

    Finally
    '破棄
    SQLiteCommand.Dispose()

    End Try

    Catch ex As Exception
    MessageBox.Show(ex.Message)
    NameTime登録 = False

    Finally
    'クローズ
    SQLiteCN.Close()
    End Try


    End Function

    Friend Function NameCount登録(ByRef SQLiteCN As System.Data.SQLite.SQLiteConnection, ByVal Names As String, ByVal Counts As Long, ByVal SQLiteOutFolder As String) As Boolean


    Dim strDBFilePath As String = SQLiteOutFolder & "\NameTime.sqlite3"
    'データベースファイルの確認
    If System.IO.File.Exists(strDBFilePath) = True Then
    Else
    '存在しない
    MessageBox.Show("データベース接続エラー", "データベースが存在しません", MessageBoxButtons.OK, MessageBoxIcon.Error)
    NameCount登録 = False
    Exit Function
    End
    End If


    '接続設定
    SQLiteCN.ConnectionString = "Version=3;Data Source=" & strDBFilePath & ";New=False;Compress=True;"
    'SQLiteコネクションオープン
    SQLiteCN.Open()
    Try
    Dim SQLiteCommand As System.Data.SQLite.SQLiteCommand
    'SQLコマンド設定
    SQLiteCommand = SQLiteCN.CreateCommand
    Try


    '登録
    SQLiteCommand.CommandText = "INSERT INTO [T_NameTime] " &
    "(" &
    "Name, " &
    "Count" &
    ") " &
    "VALUES(" &
    "'" & Names & "', " &
    Counts &
    ") "
    SQLiteCommand.ExecuteNonQuery()
    NameCount登録 = True

    Catch ex2 As Exception
    MessageBox.Show(ex2.Message)
    NameCount登録 = False

    Finally
    '破棄
    SQLiteCommand.Dispose()

    End Try

    Catch ex As Exception
    MessageBox.Show(ex.Message)
    NameCount登録 = False

    Finally
    'クローズ
    SQLiteCN.Close()
    End Try


    End Function
    End Class
    =====================================
違反を報告
引用返信

▽[全レス3件(ResNo.1-3 表示)]
■34366 / ResNo.1)  Re[1]: vb.net+SQLiteで複数データベースファイルへのトランザクション方法
□投稿者/ Hongliang 大御所(569回)-(2019/11/06(Wed) 09:36:00)
  • アイコン
    冗長でインデントもないコードは読む気がしないですが。
    
    とりあえず、複数のDBファイルにまたがったトランザクションのサンプルを記載しておきます。
    // ベタで書いたのでコンパイルが通るかどうか、ちゃんと動くかまでは確認してません。
    ポイントは、
    ・接続は片方のDBファイルに対して行う。もう片方のDBファイルはATTACH DATABASEで接続に参加させる。
     メイン側はmain.を、ATTACHした側はATTACH時のASで付けたエイリアスを、テーブル名の前につける。
    ・トランザクションはOpenしたコネクションに依存するので、Commitする前にコネクションをCloseしたりしない。
     INSERTを複数の呼び出しに分けるならコネクションはその間ずっとキープする必要がある。
     (もちろんトランザクションも)
    本筋以外では
    ・パラメータは&で文字列結合したりしないで、Parameters.AddWithValueなどでパラメータとして追加する。
    
    Class MultiFileDB
        Implements IDisposable
    
        Private m_DbFilePath1 As String = "..."
        Private m_DbFilePath2 As String = "..."
        Private m_Connection As SQLiteConnection
        Private m_Transaction As SQLiteTransaction
    
        Public Sub New()
            m_Connection = New SQLiteConnection("Data Source=" & m_DbFilePath1)
            m_Connection.Open()
            Using comm As New SQLiteCommand("ATTACH DATABASE @file AS sub", m_Connection)
                comm.Parameters.AddWithValue("@file", m_DbFilePath2)
                comm.ExecuteNonQuery()
            End Using
            m_Transaction = conn.BeginTransaction()
        End Sub
    
        Public Sub InsertToDB1(ByVal name As String, ByVal time As String)
            Using comm As New SQLiteCommand("INSERT INTO main.T_NameTime VALUES (@name, @time)", _
                                            m_Connection, m_Transaction)
                comm.Parameters.AddWithValue("@name", name)
                comm.Parameters.AddWithValue("@time", time)
                comm.ExecuteNonQuery()
            End Using
        End Sub
    
        Public Sub InsertToDB2(ByVal name As String, ByVal time As String)
            Using comm As New SQLiteCommand("INSERT INTO sub.T_NameTime VALUES (@name, @time)", _
                                            m_Connection, m_Transaction)
                comm.Parameters.AddWithValue("@name", name)
                comm.Parameters.AddWithValue("@time", time)
                comm.ExecuteNonQuery()
            End Using
        End Sub
    
        Public Sub Dispose() Implements IDisposable.Dispose
            m_Transaction.Commit()
            m_Connection.Close()
        End Sub
    End Class

違反を報告
引用返信
■34367 / ResNo.2)  Re[2]: vb.net+SQLiteで複数データベースファイルへのトランザクション方法
□投稿者/ アルファアンドベータ 一般人(2回)-(2019/11/06(Wed) 20:29:46)
  • アイコンご回答頂き有りがとうございます
    今回例題の2個にした私が悪いのですが
    7個のデータベースがある場合は
    どうATTACH DATABASEすればよろしいでしょうか?

    またパラメータでの受け渡しを初めて知り勉強になります。
    ありがとうございます。
    パラメータ受け渡しですが
    下記のパラメータは
    comm.Parameters.AddWithValue("@name", name)

    こちらとどちらがいいのでしょうか?
    comm.Parameters.Add("@name", DbType.String).Value = name ;
    タイプ指定の方が速いですか?
違反を報告
引用返信
■34368 / ResNo.3)  Re[3]: vb.net+SQLiteで複数データベースファイルへのトランザクション方法
□投稿者/ Hongliang 大御所(570回)-(2019/11/06(Wed) 20:49:40)
  • アイコン> 7個のデータベースがある場合は
    > どうATTACH DATABASEすればよろしいでしょうか?
    順次ATTACHを実施していけばいいのでは…?
    何が分からないのか分からないです。

    > どちらがいいのでしょうか?
    > comm.Parameters.AddWithValue("@name", name)
    > comm.Parameters.Add("@name", DbType.String).Value = name ;
    どちらでも構いませんしそんなに差はないと思います。
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-3]



■記事リスト / ▲上のスレッド
■34349 / 親記事)  ジェネリック型インターフェースを使った変数を扱いたい
□投稿者/ アフロ 一般人(1回)-(2019/11/01(Fri) 11:51:54)
  • アイコン環境/言語:[C# VisualStudio2012] 
    分類:[.NET] 

    ジェネリック型指定したインターフェースを扱っていて、行き詰ってしまいました。

    public interface IRoutine
    {
      // 基本の機能
    }

    public interface IRoutine<TParent> : IRoutine
    where T : IRoutine
    {
      // 親を設定する
      T Parent { get; set; }
    }

    ClassA : IRoutine<ClassA>
    {
    }

    ClassB : IRoutine<ClassB>
    {
    }

    としたとき、
    var routines = new IRoutine<T>[] {ClassA, ClassB}; // ※
    foreach(var routine in routines)
    {
      routine.Parent = 〇〇;
    }

    のように、ClassAとClassBを同じコレクションに入れて反復処理をしたいのですが、※の部分でうまく行きません。
    このような場合、変数の型指定はどのようにしてやれば良いのでしょうか?
    よろしくお願いします。

違反を報告
引用返信

▽[全レス3件(ResNo.1-3 表示)]
■34351 / ResNo.1)  Re[1]: ジェネリック型インターフェースを使った変数を扱いたい
□投稿者/ 魔界の仮面弁士 大御所(1246回)-(2019/11/01(Fri) 16:13:16)
  • アイコンNo34349に返信(アフロさんの記事)
    > public interface IRoutine<TParent> : IRoutine
    >     where T : IRoutine
    > {
    >   // 親を設定する
    >   T Parent { get; set; }
    > }

    このインターフェイスは、<T> を持つジェネリック クラスの
    子階層で定義されているということでしょうか?
    それともこれは誤記で、実際は T = TParent なのでしょうか?


    > ClassA : IRoutine<ClassA>
    これは「class ClassA : IRoutine<ClassA>」のことでしょうか?


    > var routines = new IRoutine<T>[] {ClassA, ClassB}; // ※

    元ソースが文法的に不正確である点はさておき、
     var t0 = typeof(IRoutine);
     var t1 = typeof(IRoutine<>);
     var t2 = typeof(IRoutine<ClassA>);
     var t3 = typeof(ClassA);
    において、
     t0.IsAssignableFrom(*) は、t0〜t3 いずれに対しても true
     t1.IsAssignableFrom(*) は、t1 自身以外はすべて false
     t2.IsAssignableFrom(*) は、t0〜t1 は false、t2 自身と t3 は true
     t3.IsAssignableFrom(*) は、t3 自身以外はすべて false
    という関係性を持ちます。


    ゆえに今回の型定義の場合、書くとしても
     var routines = new IRoutine[] { new ClassA(), new ClassB() };
     foreach (dynamic routine in routines)
     {
       routine.Parent = afro;
     }
    とするしかないでしょう。


    ただしこの場合、公開された
     class ClassA : IRoutine<ClassA>
     {
       public ClassA Parent { set; get; }
     }
    のような実装が対象であり、明示実装された
     class ClassA : IRoutine<ClassA>
     {
       ClassA IRoutine<ClassA>.Parent { set; get; }
     }
    なクラスに対しては使えません。
違反を報告
引用返信
■34352 / ResNo.2)  Re[2]: ジェネリック型インターフェースを使った変数を扱いたい
□投稿者/ アフロ 一般人(2回)-(2019/11/01(Fri) 17:47:28)
  • アイコン魔界の仮面弁士さん
    ご回答ありがとうございます。

    >>public interface IRoutine<TParent> : IRoutine
    >>    where T : IRoutine
    すみません。TはTParentの誤りです。

    >>ClassA : IRoutine<ClassA>
    > これは「class ClassA : IRoutine<ClassA>」のことでしょうか?
    仰る通り、class ClassA : IRoutine<ClassA>のつもりでした…

    dynamicという宣言の仕方を知らなかったので、そんな方法があったかと驚きました。
    是非取り入れてみたいと思います。
    助かりました。

    しかし、インターフェースは反復処理で力を発揮するものと思っていましたが
    ジェネリックにするとそうでもないのですかね… 今更な嘆きですが…

解決み!
違反を報告
引用返信
■34353 / ResNo.3)  Re[3]: ジェネリック型インターフェースを使った変数を扱いたい
□投稿者/ 魔界の仮面弁士 大御所(1247回)-(2019/11/01(Fri) 18:37:58)
  • アイコン2019/11/03(Sun) 15:28:57 編集(投稿者)

    No34352に返信(アフロさんの記事)
    > dynamicという宣言の仕方を知らなかったので、そんな方法があったかと驚きました。

    ジェネリックはコンパイル時点で型が確定していますが、
    dynamic の場合は実行時に動的に判定されます。

    そのため、ジェネリックに比べるとパフォーマンスは幾許か落ちますし、
    スペルミスや型の取り違いなどがあった場合も、
    コンパイル時点では検出されません。御注意ください。


    > しかし、インターフェースは反復処理で力を発揮するものと思っていましたが
    > ジェネリックにするとそうでもないのですかね…

    No34349 にあるような型定義だと使えませんが、ジェネリックの指定如何によっては
    共変性・反変性によって対処できることはありそうです。
    https://ufcpp.net/study/csharp/sp4_variance.html

    また、将来的には共変戻り値を使えるようになるかもしれません。
    ただし仮に実装されたとしても、.NET Framework では利用できず、
    .NET 5 あるいは .NET 6 以降になりそうです。
    https://ufcpp.net/blog/2019/10/pickuproslyn1004/



    > 今更な嘆きですが…
    今回の型パラメータ T が指し示す型は、
     interface IRoutine<T> : IRoutine where T : IRoutine
     {
      T Parent { get; set; }
     }
    と定義されています。

    なので、Parent プロパティが取り扱うインスタンスは、「少なくとも IRoutine 型を持つ」ことは間違いありません。

    その上で、実際のインスタンスについては、型定義が
     「class ClassA : IRoutine<ClassA>」
     「class ClassB : IRoutine<ClassB>」
    となっています。

    ClassA と ClassB は互いの継承関係を持ちません。
    両者の共通点は、「ジェネリックではない IRoutine インターフェイスを持つこと」だけです。

    この共通している IRoutine 型を使うことで、少なくとも
     『foreach (IRoutine routine in routines)』
    と書くことはできるでしょう。

    しかし IRoutine に Parent プロパティは無いので、
    このループ変数では、Parent に代入できません。

    型の確定した Parent を持つのは IRoutine ではなく、
    IRoutine<ClassA> や IRoutine<ClassB> 、
    あるいは ClassA や ClassB 型といった固有の型だけです。

    両者に共通した型が存在していない以上、このままでは
    ループ処理させることができないというわけです。
    (先述したように、dynamic やリフレクションを用いて、
    コンパイル時点ではなく実行時に解決させることならば可能)


    逆に言えば、これはつまり ClassA と ClassB の両方に対して
    「Parent プロパティを持つ共通の型」を継承もしくは実装しておくことで、
    foreach による取りまとめが可能になることを意味します。


    たとえば、こういう書き方をすることはできるでしょう。

    // 下記 2 つの定義はそのまま
    public interface IRoutine { /* 基本となる各種メンバー定義 */ }
    public interface IRoutine<T> : IRoutine where T : IRoutine
    {
      // Parent プロパティだけを定義
      T Parent { get; set; }
    }

    // 「Parent プロパティを持つ共通の型」を新たに定義
    abstract class RoutineBase : IRoutine<IRoutine>
    {
      // abstract または virtaual で定義
      public abstract IRoutine Parent { get; set; }
    }

    // 少なくとも「共通の型」を持つように実装する
    class ClassC : RoutineBase { … }
    class ClassD : RoutineBase, IRoutine<ClassD> { … }

    ***************

    var routines = new RoutineBase[] { new ClassC(), new ClassD() };
    foreach (RoutineBase routine in routines)
    {
      routine.Parent = IRoutine型の何か;
    }

    ===================

    上記では、「共通の型」として抽象クラスを設けていますが、
    もちろんインターフェイスのままでも OK です。


    // 「Parent プロパティを持つ共通の型」の定義
    interface IParent : IRoutine<IRoutine> { }


    // 少なくとも「共通の型」を持つように実装する
    class ClassE : IParent {
     public IRoutine Parent { get; set; }
    }
    class ClassF : IParent, IRoutine<ClassF> { … }

    ***************
    var routines = new IParent[] { new ClassE(), new ClassF() };
    foreach (IParent routine in routines)
    {
      routine.Parent = IRoutine型の何か;
    }


    あるいは、そもそも IRoutine<T> を廃止してしまい、上記 IParent を
     interface IParent : IRoutine
     {
       IRoutine Parent { get; set; }
     }
    にしてしまうという手もあります。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-3]






Mode/  Pass/


- Child Tree -