データリーダ+コマンド、データアダプタ+データセット、データアダプタ+データセット+コマンドビルダの比較。
そいれぞれ一長一短あるのでうまく使い分けておく方がいいみたい。これ以外の組み合わせもいろいろありそう。
Private Sub DatarederADO()
'データリーダで取得 コマンドで更新。 高速 だが SQL文などは全て自分で書く必要がある。 複数テーブルの更新などに便利。
'データリーダは接続型なので 多くのレコードを取得する場合は不向き。データセットを使用したほうが良い。
一行ずつ取得する性質上、無線、バーチャルLANなどでは不向きか?
Dim cn As New OleDbConnection
Dim cmd As New OleDbCommand
Dim dr As OleDbDataReader '読み取り専用前方スクロール
Dim myTran As OleDbTransaction
Dim i As Int32
i = System.Environment.TickCount 'システム起動後のミリ秒単位の経過時間を取得します。
Try
cmd.Connection = cn
cmd.CommandText = "SELECT * FROM Customers WHERE CustID=1"
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & Application.StartupPath & "\Order.mdb"
’VISTA上ではAccess2000形式はサポートされているらしい。Access2007でサポートされている為らしい。
cn.Open()
’こいつで読み込む
dr = cmd.ExecuteReader() ’こいつで読み込む
If dr.Read = True Then
'レコードが存在すれば
dr.Close() 'データリーダを閉じてから行わないと fetching中と言う事でエラー
myTran = cn.BeginTransaction(IsolationLevel.ReadCommitted)
cmd.Transaction = myTran
cmd.CommandText = "UPDATE Customers SET CustName='000' WHERE CustID=1"
cmd.ExecuteNonQuery()
'他にも同じ接続先への更新などが有ればSQL文を追加していく事ができる
cmd.CommandText = "UPDATE Goods SET GoodsName='9999' WHERE GoodsID='A0001'"
cmd.ExecuteNonQuery()
myTran.Commit()'確定する
End If
Catch ex As Exception
If myTran Is Nothing Then
Else
myTran.Rollback()
End If
MessageBox.Show(ex.ToString)
Debug.WriteLine(ex.ToString)
Finally
dr.Close()
cmd.Dispose()
cn.Close()
cn.Dispose()
End Try
i = System.Environment.TickCount - i
Debug.WriteLine(i & "経過しました。")
End Sub
Private Sub DatasetADO()
'データセットで取得 データアダプタのコマンドで更新。中速 データセットという非接続のテーブルをメモリ上に取得するので
'多くのレコードなどを調べてどうするか決める場合に向いている。
クライアントPCメモリ上にデータセットというテーブルの集合を取得できるので、無線、VLANに向いている。
'SQL文は自分で書く必要がある。
Dim cn As New OleDbConnection
Dim da As OleDbDataAdapter
Dim ds As New DataSet
Dim myTran As OleDbTransaction
Dim i As Int32
Dim X As Int32
X = System.Environment.TickCount 'システム起動後のミリ秒単位の経過時間を取得します。
Try
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & Application.StartupPath & "\Order.mdb"
'cn.Open'データセット取得には必要なし
da = New OleDbDataAdapter("SELECT * FROM Customers WHERE CustID=1", cn)
da.Fill(ds, "Customers") '目的のデータを取得してデータセットに格納後自動的に接続は解除される
If ds.Tables(0).Rows.Count >= 1 Then
cn.Open() 'ExecuteNonQueryには接続OPENが必要
'ゴリゴリ書いてUPDATE
da.UpdateCommand = New OleDbCommand
da.UpdateCommand.Connection = cn
myTran = cn.BeginTransaction(IsolationLevel.ReadCommitted) 'トランザクションの開始
'AccessではReadCommittedしかない?ReadUncommitted()でもエラー無しで通っているが?実際はReadCommittedしか使用しない。
'Debug.WriteLine(myTran.IsolationLevel.ToString) 'ReadCommitted
da.UpdateCommand.Transaction = myTran 'トランザクション属性付加?
da.UpdateCommand.CommandText = "UPDATE Customers SET CustName='000' WHERE CustID=1"
i = da.UpdateCommand.ExecuteNonQuery()
'他にも同じ接続先への更新などが有ればSQL文を追加していく事ができる
da.UpdateCommand.CommandText = "UPDATE Goods SET GoodsName='9999' WHERE GoodsID='A0001'"
i = da.UpdateCommand.ExecuteNonQuery() 'ここで更新してもデータグリッドには反映されない
myTran.Commit() 'トランザクションコミット
'データセットは更新されていない
'Debug.WriteLine(ds.Tables(0).Rows(0)("CustName"))
cn.Close()
End If
Catch ex As Exception
If myTran Is Nothing Then
Else
myTran.Rollback()
End If
End Try
ds.Dispose()
da.Dispose()
cn.Dispose()
X = System.Environment.TickCount - X 'システム起動後のミリ秒単位の経過時間を取得します。
Debug.WriteLine(X & "経過しました。")
End Sub
Private Sub DataSet_ComadBUilADO()
'データアダプタ + データセット + コマンドビルダ
'SQL文を書かなくても自動で更新などができるコマンドビルだだが最も低速。
'多くのフィールドを持つテーブルなどの更新に便利。ただしAccessJET4.0は99フィールドまで。ANDは50まで。それ以上になると「クエリが複雑すぎます。」のエラー
[Query is too complex]でぐぐると多くのHPがある。
''http://support.microsoft.com/?id=192716
http://www.dotnet247.com/247reference/msgs/43/216266.aspx
'また、複数のテーブルの更新となると、それごとのデータセットを取得する必要がある?
Dim cn As New OleDbConnection
Dim da As OleDbDataAdapter
Dim ds As New DataSet
Dim cmdb As New OleDbCommandBuilder 'データベースに関連付けられた DataSet への変更を調整するための単一テーブル コマンドを自動的に生成します。このクラスは継承できません。
Dim myTran As OleDbTransaction
Dim i As Int32
i = System.Environment.TickCount
Try
cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & Application.StartupPath & "\Order.mdb"
'cn.Open'必要なし
da = New OleDbDataAdapter("SELECT * FROM Customers WHERE CustID=1", cn)
da.Fill(ds, "Customers") '目的のデータを取得してデータセットに格納後自動的に接続は解除される
If ds.Tables("Customers").Rows.Count > 0 Then
cn.Open() 'トランザクションの為オープンする
'コマンドビルダでお手軽UPDATE
ds.Tables("Customers").Rows(0)("CustName") = "111"
cmdb.DataAdapter = da
da.UpdateCommand = cmdb.GetUpdateCommand
'Debug.WriteLine(da.UpdateCommand.CommandText)
myTran = cn.BeginTransaction(IsolationLevel.ReadCommitted)
da.UpdateCommand.Transaction = myTran
da.Update(ds, "Customers")
'他のテーブルは手動でUPDATE
da.UpdateCommand.CommandText = "UPDATE Goods SET GoodsName='9999' WHERE GoodsID='A0001'"
da.UpdateCommand.ExecuteNonQuery()
myTran.Commit()
cn.Close()
End If
Catch ex As System.Data.OleDb.OleDbException
If myTran Is Nothing Then
Else
myTran.Rollback()
End If
MessageBox.Show(ex.ToString)
Debug.WriteLine(ex.TargetSite)
Debug.WriteLine(ex.Message)
Debug.WriteLine(ex.ErrorCode)
Debug.WriteLine(ex.ToString)
''''Int32 Update(System.Data.DataRow[], System.Data.Common.DataTableMapping)
'''クエリが複雑すぎます。
'''-2147467259
'''''System.Data.OleDb.OleDbException: クエリが複雑すぎます。
''http://support.microsoft.com/?id=192716
http://www.dotnet247.com/247reference/msgs/43/216266.aspx
End Try
cmdb.Dispose()
ds.Dispose()
da.Dispose()
cn.Dispose()
i = System.Environment.TickCount - i
Debug.WriteLine(i & "経過しました。")
End Sub
|