0

LINQ の結果をループすることが神経質になっている状況があります。ここに私のシナリオがあります:

データベースから取得したDataTableがあり、そこからデータを次のように取得しています。

var results = from d in dtAllData.AsEnumerable()
              select new MyType
              {
                  ID = d.Field<Decimal>("ID"),
                  Name = d.Field<string>("Name")
              }

次のように並べ替え順序に応じて注文した後:

if(orderBy != "")
{
string[] ord = orderBy.Split(' ');
if (ord != null && ord.Length == 2 && ord[0] != "")
                        {
                            if (ord[1].ToLower() != "desc")
                            {
                                results = from sorted in results
                                          orderby GetPropertyValue(sorted, ord[0])
                                          select sorted;
                            }
                            else
                            {
                                results = from sorted in results
                                          orderby GetPropertyValue(sorted, ord[0]) descending
                                          select sorted;
                            }
                        }
}

GetPropertyValue メソッドは次のとおりです。

private object GetPropertyValue(object obj, string property)
    {
        System.Reflection.PropertyInfo propertyInfo = obj.GetType().GetProperty(property);
        return propertyInfo.GetValue(obj, null);
    }

この後、次のような最初のページの 25 レコードを取り出しています。

results = from sorted in results
          .Skip(0)
          .Take(25)
          select sorted;

これまでのところ順調に進んでいます。この結果をメソッドに渡してデータを操作し、目的のデータを返す必要があります。このメソッドでは、これらの 25 レコードをループしたいときに、十分な時間。私のメソッド定義は次のとおりです。

public MyTypeCollection GetMyTypes(IEnumerable<MyType> myData, String dateFormat, String offset)

試してみforeachましたが、マシンで8〜10秒かかります。次の行で時間がかかります:

foreach(var _data in myData)

while ループを試してみましたが、同じことをしています。次のように使用しました。

var enumerator = myData.GetEnumerator();
while(enumerator.MoveNext())
{
    int n = enumerator.Current;
   Console.WriteLine(n);
}

このコードには時間がかかっていますMoveNext

for私がループに行ったよりも:

int length = myData.Count();
for (int i = 0; i < 25;i++ )
{
     var temp = myData.ElementAt(i);
}

このコードには時間がかかっていますElementAt

私が間違っていることを教えてください。VS 2008 で Framework 3.5 を使用しています。

前もって感謝します

4

3 に答える 3

3

編集:問題はあなたが注文している方法にあると思います。リフレクションを使用して、最初にフェッチしてから、すべてのレコードのプロパティを呼び出しています。最初の25レコードのみが必要ですが、それらを注文するには、最初GetPropertyValueすべてのレコードを呼び出す必要があります。

リフレクションなしでこれを行うことができればはるかに良いでしょう...しかし、リフレクションを使用する必要がある場合は、すべてのレコードではなく、少なくとも1回呼び出してください。Type.GetProperty()


(いくつかの点で、これは、完全な答えそのものよりも、問題をより簡単に診断するのに役立つことと関係があります...)

ヘンクが言ったように、これは非常に奇妙です:

results = from sorted in results
          .Skip(0)
          .Take(25)
          select sorted;

あなたはほぼ間違いなく本当に欲しいだけです:

results = results.Take(25);

Skip(0)無意味です。)

実際には役に立たないかもしれませんが、コードのデバッグが簡単になります。

次の問題は、実際にすべてのコードを表示できないことです。あなたが書いた:

並べ替え順序に応じて順序付けを行った後

...しかし、注文をどのように実行しているかを示していません。

DataTableからその使用に至るまでの完全な例を示してください。

シーケンスの反復方法を変更しても効果はありません。どちらの方法でも同じことを実行しますが、前回の試行でCount()明らかにすばやく機能するのは驚くべきことです。-に固執しますが、foreachそれが何をするのかを正確に理解します。LINQは多くの遅延評価を使用しますが、それを非常に重くするようなことをした場合は、それが問題になる可能性があります。パイプライン全体を見ずに知るのは難しいです。

于 2012-06-28T15:40:28.923 に答える
0

ハイブリッド アプローチを採用する方が簡単な場合があります。

順番に:

1)データテーブルをその場でソートします。データベース レベルでこれを行うのがおそらく最善ですが、それができない場合は、DataTable.DefaultView.Sort が非常に効率的です。

dtAllData.DefaultView.Sort = ord[0] + " " + ord[1];

これは、ord[0] が列名であり、ord[1] が ASC または DESC のいずれかであると想定しています。

2) DefaultView をインデックスでページングします。

int pageStart = 0;

List<DataRowView> pageRows = new List<DataRowView>();

for (int i = pageStart; i < dtAllData.DefaultView.Count; i++ )
{
   if(pageStart + 25 > i || i == dtAllData.DefaultView.Count - 1) { break; //Exit if more than the number of pages or at the end of the rows }
   pageRows.Add(dtAllData.DefaultView[i]);
}

...そして、このはるかに小さなリストからオブジェクトを作成します... (列は Id と Name、および型と呼ばれると仮定しました)

List<MyType> myObjects = new List<MyType>();

foreach(DataRowView pageRow in pageRows)
{
  myObjects.Add(new MyObject() { Id = Convert.ToInt32(pageRow["Id"]), Name = Convert.ToString(pageRow["Name"])});
}

その後、実行していた残りの作業を続行できます。

于 2012-06-28T16:19:43.137 に答える
0

問題は、メソッドに渡されて列挙されるまで、「結果」IEnumerable が実際に評価されないことです。つまり、操作全体、dtAllData からのすべてのデータの取得、新しい型の選択 (最初の 25 だけでなく列挙型全体で発生)、そして最後に 25 を取得する操作はすべて、最初の列挙で行われます。 IEnumerable の (foreach、while、何でも)。

それがあなたの方法がとても時間がかかっている理由です。実際には、メソッド内の他の場所で定義された作業の一部を実行しています。メソッドの前にそれを行いたい場合は、メソッドの前に「ToList()」を実行できます。

于 2012-06-28T15:38:17.460 に答える