DOBON.NETプログラミング道掲示板
(現在 過去ログ4 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■34365 / inTopicNo.1)  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
    =====================================
引用返信 削除キー/
■34366 / inTopicNo.2)  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 / inTopicNo.3)  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 / inTopicNo.4)  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 ;
    どちらでも構いませんしそんなに差はないと思います。
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -