3

C# コードでパラメーター化されたクエリを使用して、Oracle データベースとやり取りしています。より読みやすい形式でステートメントをログに記録するにはどうすればよいですか?

次のようなパラメーター化されたクエリがあるとします。

INSERT INTO PERSON (ID, NAME, BIRTHDATE) VALUES (:id, :name, :birthdate)

理想的には、後で使用するためにステートメントをコピーして貼り付けることができるように、すべてのパラメーターが置き換えられたログ エントリを確認したいと考えています。

INSERT INTO PERSON (ID, NAME, BIRTHDATE) VALUES (23, ‘Mike’, TO_DATE('2003/07/09', 'yyyy/mm/dd')

私の現在のアプローチは、パラメーター化されたクエリの文字列を出力してから、すべてのパラメーターを反復処理して ToString() を使用することです。多くのパラメータがある場合、これは少し読みにくいです。次のような結果が得られます。

INSERT INTO PERSON (ID, NAME, BIRTHDATE) VALUES (:id, :name, :birthdate) [:id=23, :name=Mike, birthdate=2004/07/09 00:00:00]

私が計画している別のアプローチは、string.Replace() 関数を使用してパラメーターのプレースホルダーを置き換えることです。しかし、おそらくこれを行うためのより良い方法はありますか?

前もって感謝します。

編集1:

コード例を提供する方が良いと思いました。

この形式でパラメーター化されたクエリを使用しています (注: log4net を使用しています):

        using (OracleConnection connection = new OracleConnection(connectionString))
        using (OracleCommand command = new OracleCommand(statement, connection))
        {
            command.Parameters.AddWithValue(":id", id);
            command.Parameters.AddWithValue(":name", name);
            command.Parameters.AddWithValue(":birthdate", birthdate);
            command.Connection.Open();
            log.DebugFormat("Executing statement: {0}.", command.CommandText);
            // there I would add some more code to iterate over
            // the parameters and print them out
            command.ExecuteNonQuery();
            command.Connection.Close();
        }

Oracle コマンド オブジェクトが使用しているステートメントをログアウトする方法を探しています。私の現在のアプローチ(質問を参照)は、あまり読みにくいため、まだ満足のいくものではありません。

パラメータ化されたクエリを解析するのに役立つ API (おそらく OracleClient 名前空間にあるもの) があることを願っていました。もっと洗練された文字列置換や正規表現を行うこともできましたが、知識を集めたかったのです。私はすでにそれについていくつかの研究を行ってきましたが、何も見つかりませんでした。

4

4 に答える 4

3

NHibernate sourceで行われた方法を見る価値があるかもしれません。

ほとんどコピー/貼り付けできる「GetCommandLogString(IDbCommandコマンド)」という関数を見つけます:p

protected string GetCommandLogString(IDbCommand command)
{
    string outputText;

    if (command.Parameters.Count == 0)
    {
        outputText = command.CommandText;
    }
    else
    {
        StringBuilder output = new StringBuilder();
        output.Append(command.CommandText);
        output.Append("; ");

        IDataParameter p;
        int count = command.Parameters.Count;
        for (int i = 0; i < count; i++)
        {
            p = (IDataParameter) command.Parameters[i];
            output.Append(string.Format("{0} = '{1}'", p.ParameterName, p.Value));

            if (i + 1 < count)
            {
                output.Append(", ");
            }
        }
        outputText = output.ToString();
    }
    return outputText;
}
于 2009-01-19T23:51:11.710 に答える
2

これを後で使用するために実行可能なステートメントとして保存しようとする際の問題は、パラメーターのバージョンがハードコードされた文字列のバージョンとは異なる方法で実行されることです。文字列パラメーターなどの周り。各パラメーターのタイプに応じて手動で行う必要があります。

ログの形式はわかりませんが、ログに SQL を書き込んで、代わりにパラメーター化されたクエリを実行する方がよい場合があります。つまり、必要な変数を宣言し、値を割り当ててから、クエリを実行します。より多くの行 (または改行を回避する場合はより長い行) が作成されますが、コードをそのまま実行することができ、パラメーターを自分で置き換えることを心配する必要はありません。さらに、ログエントリは SQL インジェクションに耐性があります:)

于 2009-01-17T19:38:46.113 に答える
0

次の方法で使用できます。

INSERT INTO PERSON (ID, NAME, BIRTHDATE)
   VALUES ('"+id+"', '"+name+"', '"+birthdate+"')
于 2009-09-29T09:40:38.513 に答える
0

置換機能をうまく使いましょう。なぜだめですか?または、string.format() を使用できます。または正規表現。または組み合わせ。必要なのは文字列操作だけです。

于 2009-01-18T10:25:25.510 に答える