0

私のC#アプリは、コードスペースを乱雑にする多くの定型文を使用して多くのクエリを実行することがわかりました。また、繰り返しを避けたいのですが、これを一般的に行うためのメソッドをどのように作成できるかわかりません。

ODPを使用してOracleデータベースにアクセスしています。データウェアハウスの担当者が主キーの指定を拒否しているため、Linqを使用できません。また、LinqのODPサポートは、そうですね...彼らはむしろプラットフォームを使用してもらいたいと考えています。

すべてのクエリが異なるタイプの異なる数を返すため、実際にはリストを返すことはできません。

string gufcode = String.Empty;
double cost = 0.0;
OracleCommand GUFCommand2 = thisConnection.CreateCommand();
String GUFQuery2 = "SELECT GUF_ID, COST_RATE FROM SIMPLE_TABLE";
GUFCommand2.CommandText = GUFQuery2;
OracleDataReader GUFReader2 = GUFCommand2.ExecuteReader();
while (GUFReader2.Read())
{
    if (GUFReader2[0/**GUF_CODE**/] != DBNull.Value)
    {
        gufcode = Convert.ToString(BUFReader2[0]);
    }
    if (GUFReader2[1/**COST_RATE**/] != DBNull.Value)
    {
        cost = Convert.ToDouble(GUFReader2[1]);
    }

    effortRatioDictionary.Add(bufcode, percentageOfEffort);
}
GUFReader2.Close();

しかし、実際にはもっと多くの用語とこのようなクエリがたくさんあります。私は15かそこらのクエリを言うでしょう-15かそこらのフィールドが返されるものもあります。

この定型文をどこにでもコピー/貼り付けすると、多くの問題が発生します。たとえば、コピー貼り付けのすべてを更新しないと、間違ったリーダーを閉じて(またはさらに悪いことに)データベースに別のクエリ文字列を送信します。

私はこのようなことをしたいと思っています:

string gufQuery = "SELECT GUF_ID, COST_RATE FROM SIMPLE_TABLE";
List<something> gufResponse = miracleProcedure(gufQuery, thisConnection);

そのため、ボイラープレートのほとんどがなくなります。

シンプルなものを探しています。

4

3 に答える 3

1

いくつかのヒント:

IDisposableから派生すると、ステートメントを使用してよりクリーンなコードが可能になります。

IMOあなたの魔法の方法はもっとこのように見えるはずです:

List<T> list = doMagic("SIMPLE_TABLE", columns);

は、次のような小さな構造体の配列である可能性があります。

struct Column
{
    string Name;
    Type   DataType;
}

同じテーブル/列を頻繁に使用する場合は、列挙型を使用できる可能性があります。

または

XNAにあるVertexDeclaration、VertexElement、VertexElementFormat、およびVertexElementUsageタイプからインスピレーションを得ることができます:http://msdn.microsoft.com/en-us/library/bb197344

これは、ランダムな順序で異なる数の「入力」を処理するときに非常に役立つことが証明されています。

私の場合、そのようなものを使用して、OpenGL用の使いやすいXNAのようなフレームワークを構築することができました。

リストの返品タイプについては、私の2番目の提案を参照してください。

于 2012-07-19T15:51:16.293 に答える
1

関数を抽象化できない主な理由は、返されるデータが毎回異なるためだと思います。

つまり、読み取りの数も毎回異なります。

GUFReader2を返すこともできますが、そうすると、必要な関数内でGUFReader2を閉じることができなくなります。

オブジェクトの配列(またはリスト)を返すと言います。

手順内では、すべての行を読み、接続を閉じながらリストを返します。

呼び出し元の関数は、予想されるデータが何で、どのシーケンスになるかを常に認識しています。オブジェクトデータもキャストする必要がありますが、とにかくこのプロシージャ内でキャストします。

于 2012-07-19T14:13:29.167 に答える
0

Linqが正解でした。上記のDavidMの功績を認めますが、彼はコメントを残しただけなので、正解としてマークすることはできません。

ArrayListsを使用して半一般化されたメソッドを実行できました。

    public static ArrayList GeneralQuery(string thisQuery, OracleConnection myConnection)
    {
        ArrayList outerAL = new ArrayList();

        OracleCommand GeneralCommand = myConnection.CreateCommand();
        GeneralCommand.CommandText = thisQuery;
        OracleDataReader GeneralReader = GeneralCommand.ExecuteReader();
        while (GeneralReader.Read())
        {
            for (int i = 0; i < GeneralReader.FieldCount; i++)
            {
                ArrayList innerAL = new ArrayList();

                if (GeneralReader[i] != DBNull.Value)
                {
                    innerAL.Add(GeneralReader[i]);
                }
                else
                {
                    innerAL.Add(0);
                }
                outerAL.Add(innerAL);
            }
        }
        GeneralReader.Close();

        return outerAL;
    }

そして、このメソッドを呼び出すコードは次のようになります。

                thisConnection.Open();

                List<ProjectWrapper> liProjectCOs = new List<ProjectWrapper>();

                String ProjectQuery = "SELECT SF_CLIENT_PROJECT.ID, SF_CLIENT_PROJECT.NAMEX, SF_CHANGE_ORDER.ID, SF_CHANGE_ORDER.END_DATE, ";
                ProjectQuery += "SF_CLIENT_PROJECT.CONTRACTED_START_DATE, SF_CHANGE_ORDER.STATUS, SF_CHANGE_ORDER.TYPE, SF_CLIENT_PROJECT.ESTIMATED_END_DATE, SF_CLIENT_PROJECT.CONTRACTED_END_DATE ";
                ProjectQuery += "FROM SF_CLIENT_PROJECT, SF_CHANGE_ORDER ";
                ProjectQuery += "WHERE SF_CHANGE_ORDER.TYPE = 'New' ";
                ProjectQuery += "AND SF_CLIENT_PROJECT.ID = SF_CHANGE_ORDER.PROJECT";
                ArrayList alProjects = GeneralQuery(ProjectQuery, thisConnection);
                foreach( ArrayList proj in alProjects ) {
                    ProjectWrapper pw = new ProjectWrapper();
                    pw.projectId = Convert.ToString( proj[0] );
                    pw.projectId = Convert.ToString(proj[0]);
                    pw.projectName = Convert.ToString(proj[1]);
                    pw.changeOrderId = Convert.ToString(proj[2]);
                    pw.newEndDate = Convert.ToDateTime(proj[3]);
                    pw.startDate = Convert.ToDateTime(proj[4]);
                    pw.status = Convert.ToString(proj[5]);
                    pw.type = Convert.ToString(proj[6]);
                    if ( Convert.ToString(proj[7]) != "0" ) // 0 returned by generalquery if null
                        pw.oldEndDate = Convert.ToDateTime(proj[7]);
                    else
                        pw.oldEndDate = Convert.ToDateTime(proj[8]);
                    liProjectCOs.Add(pw);

ここには明らかな欠点がたくさんあります(ただし、以前にやろうとしていたことよりもはるかに優れています)。これは、データウェアハウスの担当者と再交渉したLinqよりもはるかに悪いものです。そこに新しい男がいて、彼はもっと助けになりました。

Linqは、コードの行を上から2分の1に減らします。これは、以前にカプセル化されていなかった方法から4分の1になります。

于 2012-07-19T19:38:33.463 に答える