中年システムエンジニアのオモチャ箱

中年システムエンジニアが初体験のブログ活動。技術情報の備忘録以外も、色々と載せていければと思います。


VB.NET String.Empty と空文字。使うのはどっち!?

VB.NET で開発をしている皆さん、文字列に空文字を設定する際に、String.Empty空文字("")のどちらを使いますか? 

 

ソースコード

Dim strTemp1 As String = String.Empty
Dim strTemp2 As String = ""

処理速度を調べてみると、たいして変わらないそうです。 

 

なので、開発チームでの方向性で決定していいのかなと思います。

 

ダメな事は、開発チーム内で String.Empty と 空文字("") を混在して使うことかな~。

 

 
文字列が空かどうか判定する場合

文字列が空かどうか判定する方法も色々ありますよね。

 

ソースコード

Dim strTemp1 As String = "Hello World!!"

If  strTemp1 = "" Then  <省略>

If  String.IsNullOrEmpty(strTemp1)  =  True  Then  <省略>

If  strTemp1.Equals("")  =  True  Then  <省略>

どれも、文字列 strTemp1 が空だったら、If 文内の処理を実行することなります。

この空かどうかの判定で使用する場合、String.Empty と空文字("")のどちらを使っても、やはり、処理速度はたいして変わらないそうです。

 

しかし、下記のように Nothing が設定されている場合は気を付ける必要があります。

 

ソースコード

Dim strTemp1 As String = Nothing

If  strTemp1 = "" Then  <省略>

If  String.IsNullOrEmpty(strTemp1)  =  True  Then  <省略>

If  strTemp1.Equals("")  =  True  Then  <省略>  ’ エラーが発生

Nothing が設定されている変数 strTemp1 に対して、Equals メソッドを使用した場合は、例外エラーが発生するので気を付けてくださいね!

文字列が空かどうかバイト数で判定する場合

文字列が空かどうかを判定する際、String.Empty や空文字("")のように文字列で判定するのではなく、バイト数で判定する方が処理速度は速いそうです。

 

ソースコード

Dim strTemp1 As String = String.Empty
If  strTemp1.Length() = 0 Then  <省略>

ただし、やはり変数 strTemp1 に Nothing が設定されている場合は、 例外エラーが発生するので気を付けてくださいね!

 

ソースコード

Dim strTemp1 As String = Nothing

If  strTemp1.Length() = 0 Then  <省略>  ’ エラーが発生

処理速度をそれ程、気にしないシステム開発であれば、開発チーム内で統一していれば問題ないと思いますが、処理速度がシビアなシステム開発の場合は気を付けてくださいね!


Visual Basicの絵本 Windowsプログラミングわかる9つの扉

VB.NET データベース開発(SQLServer、Oracle共通化)【総集編】

VB.NET を使用して、データベース開発を全 3 回に渡り紹介してきました。

あいだに他の記事を入れてしまったので、総集編としてブックマークしてもらえると便利かと思います。 

f:id:middle-aged-se:20180420142913j:plain

 

 

 

  1. VB.NET とデータベースの接続を確立
    VB.NET データ プロバイダーを使用しての DB 接続(SQLServer、Oracle共通化) を読んでください。

  2. データ抽出(SELECT 文)の実行
    VB.NET データベースの SELECT 文を実行しよう(SQLServer、Oracle共通化)を読んでください。

  3. データ更新(INSERT 文)の実行
    VB.NET データベースの INSERT 文を実行しよう(SQLServer、Oracle共通化)を読んでください。

上記記事を参考にしてクラス化することにより、SQL ServerOracle の接続を共通化し、開発効率があがればと思います。

 

参考にしてもらい、開発の役に立てれば嬉しいです。


Visual Basicの絵本 Windowsプログラミングわかる9つの扉


SQLの絵本 第2版 データベースが好きになる新しい9つの扉

VB.NET データベースの INSERT 文を実行しよう(SQLServer、Oracle共通化)

VB.NET データ プロバイダーを使用しての DB 接続(SQLServer、Oracle共通化)で、VB.NET の開発環境を使用して、SQLServerOracle の接続方法のサンプルプログラムを紹介しました。

 

VB.NET データベースの SELECT 文を実行しよう(SQLServer、Oracle共通化)で、接続したデータベースから、データの抽出(SELECT 文の実行)の接続方法のサンプルプログラムを紹介しました。

今回は、INSERT 文を実行し、データの新規追加を実施したいと思います。

INSERT 文の実行も、SQLServerOracle 共通で使用できます!

尚、VB.NET データ プロバイダーを使用しての DB 接続(SQLServer、Oracle共通化)でコーディングしてあることを前提に、下記変数を使用していきますので注意してくださいね。

  • prov
  • cmd

 

 
INSERT 文の実行(SQLServerOracle通化

 

ソースコード

Dim strSql As New System.Text.StringBuilder()
Dim param As DbParameter = Nothing
Dim trn As DbTransaction = Nothing

 

'SQL文の生成
strSql.AppendLine("INSERT INTO DEPT (")
strSql.AppendLine(" DEPT_ID")
strSql.AppendLine(",PERSON")
strSql.AppendLine(") VALUES (")
strSql.AppendLine(" :DEPT_ID_STR")
strSql.AppendLine(", :PERSON_NUM")
strSql.AppendLine(")")

 

'実行するSQL文の設定
cmd.CommandText = strSql.ToString

 

'パラメーターの初期化
cmd.Parameters.Clear()

 

'変換パラメーターの設定
param = prov.CreateParameter()
param.DbType = DbType.String
param.ParameterName = "DEPT_ID_STR"
param.Value = "A100-01"
cmd.Parameters.Add(param)
'
param = prov.CreateParameter()
param.DbType = DbType.Int32
param.ParameterName = "PERSON_NUM"
param.Value = 5
cmd.Parameters.Add(param)

 

'トランザクションの開始
trn = cmd.Connection.BeginTransaction()
cmd.Transaction = trn

 

'INSERT文を実行
cmd.ExecuteNonQuery()

 

'成功した場合、トランザクションをコミット
trn.Commit()

 

''失敗した場合、トランザクションロールバック
'trn.Rollback()

 

上記ソースプログラムのSQL 文の生成」ですが、 :PERSON_NUM 、及び、:DEPT_ID_STR の『:』は、Oracle の場合の記述方法となります。

SQL Server では『@』となり、@PERSON_NUM 、及び、@DEPT_ID_STR と記述するので注意してくださいね。

 

また、データの更新ではトランザクションという概念が存在します。

原則、下記のような手順でデータの更新を実行します。

  1. トランザクションの開始
    下記を実行します。
    trn = cmd.Connection.BeginTransaction()
    cmd.Transaction = trn
  2. 更新する SQL 文の生成、及び、設定
    今回のソースコードではトランザクションの開始よりも前で、SQL 文を生成しています。
  3. データ更新を実行
    下記を実行します。
    cmd.ExecuteNonQuery()
  4. データ更新が正常に実施されたか判定後、トランザクションの終了
    4-1. データ更新が成功した場合、コミットを実行
      下記を実行します。
      trn.Commit()
    4-2. データ更新が失敗した場合、ロールバックを実行
      下記を実行します。
      trn.Rollback()

 

変換パラメーターの設定

DbParameter オブジェクトを使用することで、SQL 文を実行する際の値をパラメーターで設定できます。

パラメーターの設定方法は下記となります。

' パラメーターを設定するオブジェクトを生成
param = prov.CreateParameter()

' 変換する値のデータ型を指定
param.DbType = DbType.Int32

' 変換する値のパラメーター文字列を指定
param.ParameterName = "PERSON_NUM"

' 変換する値を指定
param.Value = 5

' 上記設定したパラメーターを追加
cmd.Parameters.Add(param)

簡易的なソースプログラムとなりますので、エラー処理などは記載していません。

 

このソースプログラムを元にしてクラス化することにより、SQL ServerOracle の接続を共通化し、開発効率があがればと思います。

 

参考にしてもらい、開発の役に立てれば嬉しいです。


Visual Basicの絵本 Windowsプログラミングわかる9つの扉


SQLの絵本 第2版 データベースが好きになる新しい9つの扉

VB.NET データベースの SELECT 文を実行しよう(SQLServer、Oracle共通化)

VB.NET データ プロバイダーを使用しての DB 接続(SQLServer、Oracle共通化)で、VB.NET の開発環境を使用して、SQLServerOracle の接続方法のサンプルプログラムを紹介しました。

今回は、実際に SELECT 文の実行をしたいと思います。

SELECT 文の実行も、SQLServerOracle 共通で使用できます!

尚、VB.NET データ プロバイダーを使用しての DB 接続(SQLServer、Oracle共通化)でコーディングしてあることを前提に、下記変数を使用していきますので注意してくださいね。

  • prov
  • cmd

 

 
SQL 文の実行(SQLServerOracle通化

 

ソースコード

Dim strSql As New System.Text.StringBuilder()
Dim param As DbParameter = Nothing
Dim adapter As DbDataAdapter = Nothing
Dim ds As New DataSet()

 

'SQL 文の生成
strSql.AppendLine("SELECT *")
strSql.AppendLine("FROM DEPT")
strSql.AppendLine("WHERE PERSON < :PERSON_NUM")
strSql.AppendLine("AND DEPT_ID = :DEPT_ID_STR")

 

'実行する SQL 文を設定

cmd.CommandText = strSql.ToString

 

'パラメーターの初期化
cmd.Parameters.Clear()

 

'変換パラメーターの設定
param = prov.CreateParameter()
param.DbType = DbType.Int32
param.ParameterName = "PERSON_NUM"
param.Value = 5
cmd.Parameters.Add(param)
'
param = prov.CreateParameter()
param.DbType = DbType.String
param.ParameterName = "DEPT_ID_STR"
param.Value = "A100-01"
cmd.Parameters.Add(param)

 

'アダプターの生成、及び、SQL文の発行
adapter = prov.CreateDataAdapter()
adapter.SelectCommand = cmd
adapter.Fill(ds)

 

上記ソースプログラムのSQL 文の生成」ですが、 :PERSON_NUM 、及び、:DEPT_ID_STR の『:』は、Oracle の場合の記述方法となります。

SQL Server では『@』となり、@PERSON_NUM 、及び、@DEPT_ID_STR と記述するので注意してくださいね。

 

変換パラメーターの設定

DbParameter オブジェクトを使用することで、SQL 文を実行する際の値をパラメーターで設定できます。

パラメーターの設定方法は下記となります。

' パラメーターを設定するオブジェクトを生成
param = prov.CreateParameter()

' 変換する値のデータ型を指定
param.DbType = DbType.Int32

' 変換する値のパラメーター文字列を指定
param.ParameterName = "PERSON_NUM"

' 変換する値を指定
param.Value = 5

' 上記設定したパラメーターを追加
cmd.Parameters.Add(param)

 簡易的なソースプログラムとなりますので、エラー処理などは記載していません。

 

このソースプログラムを元にしてクラス化することにより、SQL ServerOracle の接続を共通化し、開発効率があがればと思います。

 

参考にしてもらい、開発の役に立てれば嬉しいです。


Visual Basicの絵本 Windowsプログラミングわかる9つの扉


SQLの絵本 第2版 データベースが好きになる新しい9つの扉

次回は、 VB.NET データベースの INSERT 文を実行しよう(SQLServer、Oracle共通化)で、データベース接続後の INSERT 文の実装方法を紹介したいと思います。

VB.NET データ プロバイダーを使用しての DB 接続(SQLServer、Oracle共通化)

データ プロバイダーを使用して、SQL Server 及び Oracle に接続するための共通処理を紹介したいと思います。

Oracle 接続環境の注意点

 Oracle に接続する際は、下記準備が必要となります。

  1. Oracle Data Access Components (ODAC) for Windows のインストール
    使用している Visual Studio のバージョンによりインストーラーが用意されています。
    2018-04-13 現在、Oracle ホームページのこちらからダウンロードすることができます。

    f:id:middle-aged-se:20180412211127j:plain

  2. 開発プロジェクトの参照設定に、Oracle.DataAccess を追加する必要があります。

    f:id:middle-aged-se:20180412211553j:plain



 
 DB接続(SQLServerOracle通化

 

ソースコード

Dim prov As DbProviderFactory = Nothing
Dim con As DbConnection = Nothing
Dim cmd As DbCommand = Nothing

 

'False:Oracle接続、True:SQLServer接続
Dim isDbSQLServer As Boolean = False
Dim strProvider As String
Dim strConnection As String

 

'DbProviderFactoryオブジェクトの生成
If isDbSQLServer Then
    'SQLServer接続の場合
    strProvider = "System.Data.SqlClient"
    strConnection = String.Format("Server={0};Database={1};User ID={2};Password={3};", _
    "192.168.1.1", _
    "sqlDB", _
    "userid", _
    "userpw")
Else
    'Oracle接続の場合
    strProvider = "Oracle.DataAccess.Client"
    strConnection = String.Format("Data Source={0};User Id={1};Password={2};", _
    "oraDB", _
    "userid", _
    "userpw")
End If

prov = DbProviderFactories.GetFactory(strProvider)

 

'DbConnectionオブジェクトの生成、及び、オープン
con = prov.CreateConnection()
con.ConnectionString = strConnection
con.Open()

 

'DBCommandオブジェクトの生成、及び、コネクションの設定
cmd = prov.CreateCommand()
cmd.Connection = con

 

上記ソースプログラムの isDbSQLServer 変数「False」を設定すると SQL Server に接続し、「True」を設定すると Oracle に接続できるような作りとなっています。

  • SQL Server の接続文字列の設定
    Server:DB サーバー名、または、IP アドレス
    Database:接続先の DB 名
    User ID:DB 接続するユーザー ID
    Password:DB 接続するパスワード

  • Oracle の接続文字列の設定
    Data Source:tnsname.ora に設定してあるデータソース名
    User ID:DB 接続するユーザー ID
    Password:DB 接続するパスワード

簡易的なソースプログラムとなりますので、エラー処理などは記載していません。

 

このソースプログラムを元にしてクラス化することにより、SQL ServerOracle の接続を共通化し、開発効率があがればと思います。

 

参考にしてもらい、開発の役に立てれば嬉しいです。


Visual Basicの絵本 Windowsプログラミングわかる9つの扉


SQLの絵本 第2版 データベースが好きになる新しい9つの扉

次回は、 VB.NET データベースの SELECT 文を実行しよう(SQLServer、Oracle共通化)で、データベース接続後の SELECT 文の実装方法を紹介したいと思います。

VB.NET メモリリークによるメモリ解放の重要性【総集編】

何回かに分けて、各種クラスのメモリリークについての対策を紹介してきました。

使用しなくなったオブジェクトをガベージコレクションの処理対象にするには、Nothing をセットするだけではなく、リソースの解放(Dispose、Clear、Close など)をした後にNothing をセットするように実装すれば、メモリリークの対策になります。

 

特に 24 時間稼働するようなアプリケーションを構築している、システムエンジニアプログラマーの皆さん、プログラミングには気をつけましょうね!

 


総集編ということでまとめてみました。
ブックマークを付けておいてもらえると便利かもしれません。

www.ma-se.com

www.ma-se.com

www.ma-se.com


Visual Basicの絵本 Windowsプログラミングわかる9つの扉

VB.NET メモリリークによるメモリ解放の重要性(ジェネリックコレクション編)

以前、メモリリーク対策について MemoryStream、DataTable の解放方法を記載しました。

 

www.ma-se.com

www.ma-se.com

今回は、頻繁に使うであろうジェネリックコレクションの List クラスについてを記載します!

調査するための基本ロジック

下記は今回のメモリリーク調査で作成したロジックです。
約 1GB のメモリを消費しています。
List クラスということで、Add メソッドで追加してみました。

 

ソースコード

Private Sub TestListBase()

    Dim objList1 As New List(Of System.IO.MemoryStream)

    '========== 約 1GB のメモリを消費 ==========
    For i = 1 To 10
        '約 100MB のオブジェクトを生成
        Dim objMem As New System.IO.MemoryStream(100000000)
        '========== 何かしらの処理 ==========
        objList1.Add(objMem)
    Next
End Sub

メモリ解放を考慮していないロジック 

では、調査するための基本ロジックを踏まえて、下記はメモリ解放の対策をしていないロジックです。
BtnListTest1 を押下し、TestList1 メソッドを実行しても問題なく動作します。
BtnListTest1 を何度押下しても(=TestList1 メソッドを何度実行しても)問題ないはずです。

 

ソースコード

Private Sub BtnListTest1_Click(sender As Object, e As EventArgs) Handles BtnListTest1.Click
    Call Me.TestList1()
End Sub

 

Private Sub TestList1()
    Dim objList1 As New List(Of System.IO.MemoryStream)

    '========== 約 1GB のメモリを消費 ==========
    For i = 1 To 10
        '約 100MB のオブジェクトを生成
        Dim objMem As New System.IO.MemoryStream(100000000)
        '========== 何かしらの処理 ==========
        objList1.Add(objMem)
    Next
End Sub

メモリ解放処理をしていなくてもメモリリークが発生しない理由は、TestList1 メソッドの呼び出しが完了した段階で、.NET 側でメモリ解放処理(ガベージコレクションの発動)を暗黙的におこなっているからです。

 

では、下記のように BtnListTest1 を 2 回押下した動作と同じロジックを実行した場合は、どうなるでしょう?

 

ソースコード

Private Sub BtnListTest1_Click(sender As Object, e As EventArgs) Handles BtnListTest1.Click
    Call Me.TestList1()
End Sub

 

Private Sub TestList1()
    Dim objList1 As New List(Of System.IO.MemoryStream)
    Dim objList2 As New List(Of System.IO.MemoryStream)

 

    '========== 約 1GB のメモリを消費 ==========
    For i = 1 To 10
        '約 100MB のオブジェクトを生成
        Dim objMem As New System.IO.MemoryStream(100000000)
        '========== 何かしらの処理(その1) ==========
        objList1.Add(objMem)
    Next

 

    '========== 約 1GB のメモリを消費 ==========
    For i = 1 To 10
        '約 100MB のオブジェクトを生成
        Dim objMem As New System.IO.MemoryStream(100000000)
        '========== 何かしらの処理(その2) ==========
        objList2.Add(objMem)
    Next

End Sub

結果は、途中で Out Of Memoty のエラーで落ちますよね。
BtnListTest1 を 2 回押下した動作と同じ処理を行っているのに、何故、連続で同じロジックを実行するとエラーが発生するのでしょうか?
理由は、objList1 のメモリ解放処理を実施せずに、同一メソッド内で objList2 の生成でメモリ消費をしているためです。
BtnListTest1 を 2 回押下した場合は、TestList1 メソッドを 2 回呼び出していたので(暗黙的にメモリ解放を行っていたので)、問題なく動作しました。

これは悪い例なので、マネしないようにしてください。

 

 
メモリ解放を考慮したロジック

List クラスには、Dispose メソッドは存在しません。
では、Nothing をセットすればガベージコレクションの処理対象になるのかな?かな??

結論から言うと Nothing をセットするだけではダメです!!

 

VB.NET メモリリークによるメモリ解放の重要性(DataTable 編)でも、記載しましたが Clear メソッド実行後に Nothing をセットしましょう!

 

ソースコード

Private Sub BtnListTest1_Click(sender As Object, e As EventArgs) Handles BtnListTest1.Click
    Call Me.TestList1()
End Sub

 

Private Sub TestList1()
    Dim objList1 As New List(Of System.IO.MemoryStream)
    Dim objList2 As New List(Of System.IO.MemoryStream)

 

    '========== 約 1GB のメモリを消費 ==========
    For i = 1 To 10
        '約 100MB のオブジェクトを生成
        Dim objMem As New System.IO.MemoryStream(100000000)
        '========== 何かしらの処理(その1) ==========
        objList1.Add(objMem)
    Next
    objList1.Clear()
    objList1 = Nothing

 

    '========== 約 1GB のメモリを消費 ==========
    For i = 1 To 10
        '約 100MB のオブジェクトを生成
        Dim objMem As New System.IO.MemoryStream(100000000)
        '========== 何かしらの処理(その2) ==========
        objList2.Add(objMem)
    Next
    objList2.Clear()
    objList2 = Nothing

End Sub

 

このように、使用しなくなったオブジェクトをガベージコレクションの処理対象にするには、Nothing をセットするだけではなく、リソースの解放(Dispose、Clear、Close など)をした後にNothing をセットするように心がけましょうね。


Visual Basicの絵本 Windowsプログラミングわかる9つの扉