6

データテーブルを返すデータ層選択メソッドがあります。これは、厳密に型指定されたジェネリック List を返すビジネス層メソッドから呼び出されます。

私がやりたいことは、この質問と非常に似ています (ただし、同じではありません):
How do you convert a DataTable into a generic list?

異なるのは、リストにデータ行ではなく厳密に型指定されたオブジェクトを含めたいということです (また、ここではまだ linq を利用できません)。

性能が気になります。次に、ビジネス層のメソッドがプレゼンテーション層から呼び出され、結果が反復されてユーザーに表示されます。ビジネス層で余分なイテレーションを追加するのは非常に無駄に思えます。プレゼンテーションのためにすぐにやり直すだけです。そのため、これをできるだけ迅速に行いたいと考えています。

これはよくある作業なので、何度も繰り返せる良いパターンを本当に探しています。

4

6 に答える 6

9

上記のサンプルの問題は、非常に遅いことです。約 400 行の DataTable があり、この変換には 5 ~ 6 秒かかります。

これはかなり一般的なタスクのように思えますが、ここに、よりパフォーマンスの高いソリューションを提供する人がいないことに驚いています。

* アップデート!!* 念のため、DataTable を反復処理してリストに追加するのではなく、LINQ を使用して変換してみようと思いました。以下は私がしたことです:

   List<MyObject> returnList = new List<MyObject>();

   MyDataTable dtMyData = new MyTableAdapter().GetMyData();

   returnLists = (from l in dtMyData
                 select new MyObject
                 {
                    Active = l.IsActive,
                    Email = l.Email,
                    //...
                    //About 40 more properties
                    //...
                    ZipCode = l.Zipcode
                  }).ToList();

最初の方法 (各行を繰り返す) は 5.3 秒かかり、LINQ を使用する方法は 1.8 秒かかりました!

于 2010-05-21T14:43:37.533 に答える
7

DataTableと型付きオブジェクトの構造を事前に知っていますか? デリゲートを使用してマッピングを行うことができます。そうでない場合 (つまり、Typeと プロパティしか知らない場合)、動的メンバー アクセスを高速化する方法があります ( などHyperDescriptor)。

いずれにせよ、反復子ブロックを検討してください。そうすれば、オブジェクトをまったく 2 回バッファリングする必要がなくなります。もちろん、小さな行数のみを扱っている場合、これは問題ではありません。

それらの点を明確にできますか?詳細をもっと追加できます...

最も単純に言えば、何が問題なのか:

DataTable table = new DataTable {
    Columns = {
        {"Foo", typeof(int)},
        {"Bar", typeof(string)}
     }
};
for (int i = 0; i < 5000; i++) {
    table.Rows.Add(i, "Row " + i);
}

List<MyType> data = new List<MyType>(table.Rows.Count);
foreach (DataRow row in table.Rows) {
    data.Add(new MyType((int)row[0], (string)row[1]));
}

(上記の問題は正しいアプローチを導くかもしれません...)

于 2009-01-13T22:18:24.703 に答える
0

いずれにせよ、データ行を反復処理してオブジェクトに変換する必要がありますが、データ行のコレクションを取得し、要求されたときに各アイテムをすべてではなくオブジェクトタイプに変換するコンストラクターを使用して、カスタムコレクションを作成できます。一度。

を実装するカスタムコレクションを定義するとしますIList<T>。その場合、2つの内部フィールド(データ行のコレクションへの参照と)を持つことができますList<T>。はList<T>、データ行のコレクションの長さに初期化されますが、値はnullになります。

これで、インデクサーで、List<T>にそのインデックスの値が含まれているかどうかを確認できます。含まれていない場合は、有用な手段を使用してオブジェクトを作成し、そこに格納してから返すことができます。

これにより、オブジェクトの作成が要求されるまで延期され、要求されたオブジェクトのみが作成されます。

オブジェクトには、おそらくDataRowを取得するコンストラクターが必要になるか、オブジェクトを作成するために何らかのファクトリが必要になりますが、それは別のトピックです。

于 2009-01-13T22:31:24.243 に答える
0

シンプルなコンソールアプリでマークの回答にユーザーフレンドリーを提供するためだけに:

class Program
{
    static void Main(string[] args)
    {
        //define a DataTable obj
        DataTable table = new DataTable
        {
            Columns = {
            {"Foo", typeof(int)},
            {"Bar", typeof(string)}
         }
        };
        //populate it the DataTable 
        for (int i = 0; i < 3; i++)
        {
            table.Rows.Add(i, "Row " + i);
        }

        List<MyType> listWithTypedObjects= new List<MyType>(table.Rows.Count);
        foreach (DataRow row in table.Rows)
        {
            listWithTypedObjects.Add(new MyType((int)row[0], (string)row[1]));
        }

        Console.WriteLine(" PRINTING THE POPULATED LIST ");
        foreach (MyType objMyType in listWithTypedObjects)
        {
            Console.Write(" I have object of the type " + objMyType.ToString() + " => " );
            Console.Write(" with Prop1OfTypeInt " + objMyType.Prop1OfTypeInt.ToString() + " , ");
            Console.WriteLine(" with Prop1OfTypeInt " + objMyType.Prop2OfTypeString.ToString() + "  "); 
        }

        Console.WriteLine(" \n \n \n HIT A KEY TO EXIT THE PROGRAM ");
        Console.ReadKey();
    }
}

class MyType {

    public int Prop1OfTypeInt { get; set; }
    public string Prop2OfTypeString { get; set; } 

    /// <summary>
    /// Note the order of the passed parameters is important !!!
    /// </summary>
    public MyType( int prop1OfTypeInt , string prop2OfTypeString)
    {
        this.Prop1OfTypeInt = prop1OfTypeInt;
        this.Prop2OfTypeString = prop2OfTypeString; 

    }
}
于 2010-01-26T07:36:13.263 に答える
-5
public partial class issuereceive_manageroffice_bal
{
    public int issue_id{get;set;}
    public string process{get;set;}
    public DateTime issue_date{get;set;}
    public TimeSpan issue_time{get;set;}
    public string eg_no{get;set;}
    public string lotno{get;set;}
    public string clarity{get;set;}
    public string sieves{get;set;}
    public string shape{get;set;}
    public double issue_carat{get;set;}
    public int issue_pieces{get;set;}
    public int receive_pieces{get;set;}
    public double receive_carat{get;set;}
    public int kp_pieces{get;set;}
    public decimal kp_carat{get;set;}
    public double loss{get;set;}
    public string issue_manager{get;set;}
    public string issue_by{get;set;}
    public string receive_by{get;set;}
    public int status{get;set;}
    public DateTime receive_date{get;set;}
    public string receive_time{get;set;}
    public int factory_id{get;set;}

}


List<issuereceive_manageroffice_bal> issue_receive_list = new List<issuereceive_manageroffice_bal>();
issue_receive_list =
      (from DataRow dr in DataTable.Rows
      select new issuereceive_manageroffice_bal()
           {
               issue_id = 0,
               issue_time = TimeSpan.Parse("0"),
               receive_time = null,
               shape = null,
               process = dr["process"].ToString(),
               issue_date = Convert.ToDateTime(dr["issue_date"]),
               eg_no = dr["eg_no"].ToString(),
               lotno = dr["lotno"].ToString(),
               clarity = dr["clarity"].ToString(),
               sieves = dr["sieves"].ToString(),
               issue_carat = dr["issue_carat"].ToString() != "" ? double.Parse(dr["issue_carat"].ToString()) : 0,
               issue_pieces = dr["issue_pieces"].ToString() != "" ? int.Parse(dr["issue_pieces"].ToString()) : 0,
               receive_carat = dr["receive_carat"].ToString() != "" ? double.Parse(dr["receive_carat"].ToString()) : 0,
               kp_pieces = dr["kp_pieces"].ToString() != "" ? int.Parse(dr["kp_pieces"].ToString()) : 0,
               kp_carat = dr["kp_carat"].ToString() != "" ? decimal.Parse(dr["kp_carat"].ToString()) : 0,
               loss = dr["loss"].ToString() != "" ? double.Parse(dr["loss"].ToString()) : 0,
               issue_manager = dr["lotno"].ToString(),
               issue_by = dr["issue_by"].ToString(),
               receive_by = dr["receive_by"].ToString(),
               status = dr["status"].ToString() != "" ? int.Parse(dr["status"].ToString()) : 0,
               receive_date = Convert.ToDateTime(dr["receive_date"]),
               factory_id = dr["factory_id"].ToString() != "" ? int.Parse(dr["factory_id"].ToString()) : 0,

           }).ToList();
于 2015-04-10T07:42:55.317 に答える