42069


タイトルの件、SELECT文のWHERE句の手前までは、固定化し  
WHERE句以降は利用側でいろいろと条件を変更したいので、  
以下のようなシグネチャのメソッドを検討しています。

[code]

    List<T> select( DbTransaction tran, string whereCondition)
    {
        string beforeWhereSql = (ファイルから読み込み);
        string executeSql = beforeWhereSql + whereCondition;
        /* SQL 実行処理*/
    　　　
    　　　return 検索結果
    }
    
[/code]

Ｔは、検索結果の型です。  
外からwhereConditionを渡す場合に、利用側でこのstringを作成する必要がありますが、  
後でこのwhereCondition部分を指しかえれるような仕組みを検討しています。  
目的は、OracleでもMySQLにも対応できるように、SQL文は後から差し替えたいです。

なお、whereCondition部分は、利用アプリ側で動的に作成する必要があります。

.Net Frameworkは4.6になります。

何かノウハウ等ありましたら情報を頂けると幸いです。


CC BY-SA 3.0
2018-03-01T01:14:08.753
42064
2018-03-01T04:15:40.213
9228
question
c#
C# SQL文のwhere句以降を指し換える仕組みを検討したいです。


一番基本的なノウハウとしては、最低限データベース層とビジネスロジック層は分けてプログラム設計をします。  
その場合、SQL の WHERE句 の条件はおそらくビジネスロジックに属すると思います。  
Oracle と MySQL の違いを吸収するのが、データベース層の仕事です。  
Entity Framework などを使うとデータベース層の実装が簡単になります。


CC BY-SA 3.0
2018-03-01T02:10:16.147
42065
2018-03-01T02:10:16.147
18616
42064
answer


前提としてクエリーの条件自体を文字列として指定させるべきではありません。

まず、第三者から渡されたSQLフラグメントをそのまま使用することは深刻なセキュリティホールになりえます。一番単純な例としては

[code]

    "SELECT * FROM table1 " + "WHERE 1 = 1; DROP TABLE table1";
    
[/code]

のように別のSQLステートメントを追加されることも考慮してください。  
このような攻撃に対しては引数の値が文法的に問題ないか検証する必要があるのですが、究極的にはSQLパーサーを作らなけれなならないため筋の良い方法とは言えません。`WHERE`句をそのまま受け取るメソッドを作るとしても、`public`にすべきではありません。

ですので引数を単純な値として扱うためにパラメーターを使用して

[code]

    if (value != null)
    {
        sql += " AND Hoge = :value";
        dbCommand.Parameters.Add(":value", value);
    }
    
[/code]

のようにSQL生成メソッド側で想定している条件に渡された値を入れる形にしなければなりません。このパラメーターの書式はRDBMSごとに異なりますので、仮にこの方針で作るとしたらこの処理は差し替え可能にする必要があります。

以上の理由により文字列処理によるSQL生成には限界がありますし、現代的な方法とは言えません。行ってしまえば **極力SQLを文字列として扱うべきでない**
というのがノウハウです。

一方Entity
Frameworkに代表されるORMでは検索条件として文字列ではなく`System.Linq.Expressions.Expression`型を採用しています。これはC#のラムダ式ですので、多彩な条件を表すことが出来ます。単純な検索であれば

[code]

    // Expression<Func<T, bool>> predicate = e => e.Hoge == value;
    db.Table1.Where(predicate).ToList();
    
[/code]

だけで済みます。RDBMSは基本的には参照ライブラリと接続文字列周りの設定を入れ替えれば変更可能です。

またORMであっても`DataBase.SqlQuery`(EFの場合)のようなメソッドなどから文字列によるクエリーも提供していることが多いので、切り替えられるところからORMに変更していくのが良いのではないでしょうか。


CC BY-SA 3.0
2018-03-01T04:15:40.213
42069
2018-03-01T04:15:40.213
5750
42064
answer