DBアプリケーションで避けては通れない ExecuteReader メソッドですが、これってイマイチですよね。 ひとまず適当にサンプル書いてみます。
Private Sub SelectRader() Using cn As IDbConnection = New SqlClient.SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=AdventureWorks2016CTP3;Integrated Security=SSPI") cn.Open() Dim sql = "select * from Person.Person where BusinessEntityID < 1000 order by BusinessEntityID" Using cmd As IDbCommand = New SqlClient.SqlCommand(sql, cn) Using r = cmd.ExecuteReader Do While r.Read() Console.WriteLine(r("BusinessEntityID")) Loop End Using End Using End Using End Sub
これの何がいやってForEach文で書けない。
Loop文の条件がイマイチわかりづらい。覚えりゃいいんですけどなんか覚えたくない。 ForEach文で書けたらそんなこと気にする必要もない。 ForEach文で書けないかなぁ…
拡張メソッドで解決だ
拡張メソッドでラップしてやればよさげ! まずは完成形をイメージしてみる。
これが
Using r = cmd.ExecuteReader Do While r.Read() Console.WriteLine(r("BusinessEntityID")) Loop End Using
こんな感じになれば!
For Each r In cmd.ExecuteReader Console.WriteLine(r("BusinessEntityID")) Next
拡張メソッドはこんな感じ
ExecuteReaderという名前だと通常のものと紛らわしくなるので別名を付けますか。 他のメソッド名とそろえると「ExecuteDataIterator」ってことにします。
<Extension> Public Iterator Function ExecuteDataIterator(source As IDbCommand) As IEnumerable(Of IDataReader) Using r = source.ExecuteReader Do While r.Read() Yield r Loop End Using End Function
適用してみるとこんな感じ
Private Sub SelectRader() Using cn As IDbConnection = New SqlClient.SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=AdventureWorks2016CTP3;Integrated Security=SSPI") cn.Open() Dim sql = "select * from Person.Person where BusinessEntityID < 1000 order by BusinessEntityID" Using cmd As IDbCommand = New SqlClient.SqlCommand(sql, cn) For Each r In cmd.ExecuteDataIterator Console.WriteLine(r("BusinessEntityID")) Next End Using End Using End Sub
戻り値は使い慣れた IDataReader なので覚えることはあまりないです。 字下げも減るし、コード量も減るし、終了分岐を間違えることもなくていい感じ。
余談
突き詰めるとここまで行けるはず!っていうか、自分は最近コレで書いてます。
Private Sub SelectRader() Dim sql As String = "select * from Person.Person where BusinessEntityID < 1000 order by BusinessEntityID" For Each r In sql.ExecuteDataIterator Console.WriteLine(r("BusinessEntityID")) Next End Sub
コネクション開閉、DBコマンド生成処理をすべて拡張メソッドにやらせてます。 コーディング量は約半分!