1

プロジェクトのDALで通常使用する一連のメソッド用にNpgSQLのラッパーを作成しました。それらのうちの2つは、通常、DataReaderから直接DTOを入力するために使用します。通常、フィルヘルパーメソッドでは、DTOをインスタンス化し、Datareaderのデータを対応するプロパティにマッピングするプロパティを反復処理します。ほとんどの場合、fillメソッドが生成されます。

プロパティの多くをnullにするか、DTOのデフォルト値を使用することを許可しているため、プロパティを入力する前に、dataReaderのデータがプロパティに対して有効かどうかを確認するメソッドを使用しました。したがって、IsValidString( "fieldname")メソッドとDRGetString( "fieldname")メソッドを次のように使用します。

public bool IsValidString(string fieldName)
{
        if (data.GetOrdinal(fieldName) != -1
            && !data.IsDBNull(data.GetOrdinal(fieldName)))
            return true;
        else
            return false;
}

public string DRGetString(string fieldName)
{
        return data.GetString(data.GetOrdinal(fieldName));
}

私のfillメソッドは、クエリを実行したメソッドに遅延し、次のようになります。

public static object FillObject(DataParse<PostgreSQLDBDataParse> dataParser)
{
     TipoFase obj = new TipoFase();   

     if (dataParser.IsValidInt32("T_TipoFase"))
        obj.T_TipoFase = dataParser.DRGetInt32("T_TipoFase");

     if (dataParser.IsValidString("NM_TipoFase"))
        obj.NM_TipoFase = dataParser.DRGetString("NM_TipoFase");

            //...rest of the properties .. this is usually autogenerated by a T4 template

     return obj;
}

これは、2.02より前のNpgSQLでは正常に機能していました。。GetOrdinalメソッドが呼び出されたときに、フィールドがdataReaderに存在しなかった場合は、単に-1が返されます。IsValidString()でfalseを返し、次のプロパティにスキップするのは簡単です。存在しないフィールドをチェックすることによるパフォーマンスのヒットは、事実上無視できました。

残念ながら、NpgSQLを変更すると、フィールドが存在しない場合にGetOrdinalが例外をスローします。コードをtry/catchでラップし、catch内でfalseをスローするという簡単な回避策があります。しかし、特にデバッグモードに入ると、パフォーマンスの低下を感じることができます。長いリストへの記入には数分かかります。

おそらく、NpgSQLには、このメソッドの後方互換性をサポートするために接続文字列(互換性)に追加できるパラメーターがありますが、それが正しく機能することはありません(接続文字列の形式が正しくないため、常に例外が発生します)。とにかく、私はより良い回避策のための提案を探しています。データリーダーからオブジェクトを入力する、または何らかの方法で例外の問題を回避するためのより良い方法はありますか?

4

1 に答える 1

0

私は自分の問題の解決策を作成しました。それは大きな変更を必要とせず、興味深いパフォーマンスを示します(またはそう思われます)。新しい解析ライブラリ/ラッパーである可能性があります。

基本的に、dataReaderのフィールドを反復処理し、それぞれをコレクション(私の場合はリスト)にコピーします。次に、有効なデータを確認し、有効と見なされた場合は、データをオブジェクトのプロパティにコピーします。

だから私は持っているでしょう:

public class ParserFields
{
    public string FieldName { get; set; }
    public Type FieldType { get; set; }
    public object Data { get; set; }
}

そして、私は以下を使用してオブジェクトを埋めます:

public static object FillObjectHashed(DataParse<PostgreSQLDBDataParse> dataParser)
    {
        //The the Field list with field type and data
        List<ParserFields> pflist = dataParser.GetReaderFieldList(); 

        //create resulting object instance
        CandidatoExtendido obj = new CandidatoExtendido();

        //check for existing field and valid data and create object
        ParserFields pfdt = pflist.Find(objt => objt.FieldName == "NS_Candidato");
        if (pfdt != null && pfdt.FieldType == typeof(int) && pfdt.Data.ToString() != String.Empty)
            obj.NS_Candidato = (int)pfdt.Data;

        pfdt = pflist.Find(objt => objt.FieldName == "NM_Candidato");
        if (pfdt != null && pfdt.FieldType == typeof(string) && pfdt.Data.ToString() != String.Empty)
            obj.NM_Candidato = (string)pfdt.Data;

        pfdt = pflist.Find(objt => objt.FieldName == "Z_Nasc");
        if (pfdt != null && pfdt.FieldType == typeof(DateTime) && pfdt.Data.ToString() != String.Empty)
            obj.Z_Nasc = (DateTime)pfdt.Data;

        //...

        return obj;
    }

違いを確認するために、バリエーションのタイミングを調整しました。612件の結果を返す検索を行いました。最初に、データベースに2回クエリを実行し、クエリの最初の実行とその後のキャッシュに関連する違い(および非常に重要な場合)を考慮に入れました。私のFillObjectメソッドは、結果リストに追加する目的のオブジェクトの新しいインスタンスを作成しただけです。

  • オブジェクトのインスタンスのリストへの最初のクエリ:2896Kティック
  • 2番目のクエリ(最初のクエリと同じ):1141Kティック

次に、以前の塗りつぶしオブジェクトを使用してみました

  • 戻りデータまたはデフォルトで満たされた目的のオブジェクトのリストに、すべてのオブジェクトのプロパティをチェックします:3323Kティック
  • 目的のオブジェクトを一覧表示するには、検索で返されたオブジェクトのプロパティのみをチェックします:1127Kティック
  • ルックアップリストを使用して目的のオブジェクトを一覧表示するには、返されたフィールドのみをチェックします:1097Kティック
  • ルックアップリストを使用して目的のオブジェクトを一覧表示するには、すべてのフィールドをチェックします(いくつかのネストされたプロパティを除く):1107Kティック

私が使用していた元のコードは、目的のフィールドに限定された方法を使用した場合の3倍近くのティックを消費していました。それを殺すところの例外。

fillobjectメソッドの新しいコードを使用すると、目的のフィールドをチェックするだけの場合と比較して、存在しないファイルをチェックするためのオーバーヘッドが最小限に抑えられます。

少なくとも今のところ、これはうまく機能しているようです。いくつかの最適化を探してみてください。どんな暗示もありがたいです!

于 2010-03-04T00:52:46.440 に答える