Index: [Article Count Order] [Thread]

Date:  Mon, 13 Jul 2009 12:45:14 +0900
From:  "IWPS) 平本" <t.hiramoto@....jp>
Subject:  [coding-standard:00014] 埋め込みクエリ
To:  コーディング規約の会 <coding-standard@....jp>
Message-Id:  <20090713123725.846F.59F887E@....jp>
X-Mail-Count: 00014

ひらぽんです。

もう一つお題を上げさせていただきます。
「埋め込みクエリ」の規約です。C#・VB.NET 共通で使えます。


様々な現場で、以下のような埋め込みクエリを見かけます。

----------------------------------------------------------------
Dim strSQL As String = _
    "SELECT c.id, c.code, c.name, c.zipcode, c.address, c.telphone FROM customer " & _
    "c WHERE c.id = " & id.ToString & " AND c.name LIKE '%" & name & "%' ・・・・"
----------------------------------------------------------------

これだとクエリが大きくなるほど可読性が低下する上、サーバーでログを見るとき

----------------------------------------------------------------
SELECT c.id, c.code, c.name, c.zipcode, c.address, c.telphone FROM customer ・・・・・ 
----------------------------------------------------------------

と一行の長文になってしまい、クエリに問題があっても、どこに問題があるのかチェックしずらくなります。

しかし System.Text.StringBuilder をうまく使えば、クエリの可読性が劇的に向上し、
サーバーに流れたクエリを拾う際も非常に見やすくなります。

----------------------------------------------------------------
Dim query As New System.Text.StringBuilder()
With query
    .AppendLine("SELECT ")
    .AppendLine("   c.id, ")
    .AppendLine("   c.code, ")
    .AppendLine("   c.name, ")
    .AppendLine("   c.zipcode, ")
    .AppendLine("   c.address, ")
    .AppendLine("   c.telphone ")
    .AppendLine("FROM ")
    .AppendLine("   customer ")
    .AppendLine("WHERE c.id = " & id.ToString & " ")
    .AppendLine("AND   c.name LIKE '%" & Name & "%' ")
    ・・・・
End With
----------------------------------------------------------------

さらにクエリの一行目にメソッド名をコメントとして設定すると、
どのクラスのどのメソッドから投げられたのか、すぐ判るようになります。

----------------------------------------------------------------
Dim query As New System.Text.StringBuilder()
With query
    .AppendLine("-- CompanyName.TechnologyName.FeatureName.ClassName.MethodName")
    .AppendLine("SELECT ")
    .AppendLine("   c.id, ")
    .AppendLine("   c.code, ")
    .AppendLine("   c.name, ")
    .AppendLine("   c.zipcode, ")
    .AppendLine("   c.address, ")
    .AppendLine("   c.telphone ")
    .AppendLine("FROM ")
    .AppendLine("   customer ")
    .AppendLine("WHERE c.id = " & id.ToString & " ")
    .AppendLine("AND   c.name LIKE '%" & name & "%' ")
    ・・・・
End With
----------------------------------------------------------------

これならサーバーに流れるクエリは以下のようになり、大変保守しやすくなります。

----------------------------------------------------------------
-- CompanyName.TechnologyName.FeatureName.ClassName.MethodName
SELECT 
   c.id, 
   c.code, 
   c.name, 
   c.zipcode, 
   c.address, 
   c.telphone 
FROM 
   customer 
WHERE c.id = 24 
AND   c.name LIKE '%hogehoge%'
----------------------------------------------------------------

ただし上記のクエリは、セキュリティ上まだ不安が残ってます。
以下のように SqlParameter クラスを使うと、SQLインジェクション対策ができます。

----------------------------------------------------------------
Dim query As New System.Text.StringBuilder()
With query
    .AppendLine("-- CompanyName.TechnologyName.FeatureName.ClassName.MethodName")
    .AppendLine("SELECT ")
    .AppendLine("   c.id, ")
    .AppendLine("   c.code, ")
    .AppendLine("   c.name, ")
    .AppendLine("   c.zipcode, ")
    .AppendLine("   c.address, ")
    .AppendLine("   c.telphone ")
    .AppendLine("FROM ")
    .AppendLine("   customer ")
    .AppendLine("WHERE c.id = @id ")
    .AppendLine("AND   c.name LIKE CONCAT( '%', @name, '%' ))
    ・・・・
End With

Dim command As New SqlCommand(query.ToString())
With command.Parameters
    .Add(New SqlParameter("id", id))
    .Add(New SqlParameter("name", name))
End With
----------------------------------------------------------------

要点をまとめると

1.埋め込みクエリは、& 演算子で結合せず、System.Text.StringBuilder を使う

2.StringBuilder.Append() ではなく StringBuilder.AppenLine() メソッドで結合する

3.一行目には、メソッド名をコメントに加える

4.セキュリティ強化のため、SqlParameter を使ってクエリパラメータに値を渡すようにする


メールだと見づらいかもしれませんので、参考のため、私のブログにも挙げておきます。
http://blogs.yahoo.co.jp/hilapon/3515173.html

いかがでしょうか?(^ω^;

-- 
IWPS) 平本 <t.hiramoto@....jp>