0

ネットワークの待ち時間を避けるために、3 つのテーブルすべてから一度にデータを取得しています。データのフェッチは非常に高速ですが、結果をループすると多くの時間がかかります

Int32[] arr = { 1 };
var query = from a in arr
            select new
            {
              Basket = from b in ent.Basket
                       where b.SUPERBASKETID == parentId
                       select new
                       {
                           Basket = b,
                           ObjectTypeId = 0, 
                           firstObjectId = "-1",
                       },

              BasketImage = from b in ent.Image
                            where b.BASKETID == parentId
                            select new
                            {
                                Image = b,
                                ObjectTypeId = 1, 
                                CheckedOutBy = b.CHECKEDOUTBY,
                                firstObjectId = b.FIRSTOBJECTID,
                                ParentBasket = (from parentBasket in ent.Basket
                                                where parentBasket.ID == b.BASKETID
                                                select parentBasket).ToList()[0],
                            },

              BasketFile = from b in ent.BasketFile
                           where b.BASKETID == parentId
                           select new
                           {
                               BasketFile = b,
                               ObjectTypeId = 2, 
                               CheckedOutBy = b.CHECKEDOUTBY,
                               firstObjectId = b.FIRSTOBJECTID,
                               ParentBasket = (from parentBasket in ent.Basket
                                               where parentBasket.ID == b.BASKETID
                                               select parentBasket),
                           }
            };

//Exception handling

var mixedElements = query.First();
ICollection<BasketItem> basketItems = new Collection<BasketItem>();

//Here 15 millis has been used
//only 6 elements were found

if (mixedElements.Basket.Count() > 0)
{
  foreach (var mixedBasket in mixedElements.Basket){}
}

if (mixedElements.BasketFile.Count() > 0)
{
  foreach (var mixedBasketFile in mixedElements.BasketFile){}
}

if (mixedElements.BasketImage.Count() > 0)
{
  foreach (var mixedBasketImage in mixedElements.BasketImage){}
}

//the empty loops takes 811 millis!!
4

2 に答える 2

1

IEnumerableforeach ループで使用しています。実装は、要求されたときにのみデータを準備する必要があります。このように、上記のコードがデータに遅延アクセスしていることをお勧めします。つまり、項目を列挙するときだけです (実際には を呼び出したときに発生しますCount())。

System.Diagnostics.Stopwatchへの呼び出しを回避して、それがあなたCount()が見ている時間の大部分を占めているかどうかを確認してください。

entコードサンプルでのタイプを指定していないため、ここでこれ以上コメントすることはできません。

于 2009-10-30T07:57:55.157 に答える
1

foreach ステートメントの前にカウントをチェックするのはなぜですか? 結果がない場合、foreach はただちに終了します。

あなたのクエリは実際にはすべて延期されています - それらはあなたがデータを要求したときに実行されます。最も外側のクエリが LINQ to Objects クエリであることを忘れないでください。呼び出しent.Basket.Where(...).Select(...)などの結果を返すだけで、実際にはクエリを実行しません。

3 つのクエリを一度に実行するという計画は、実際には機能していません。ただし、カウントを個別に要求すると、実際には各データベース クエリを 2 回実行することになります。

このコードの「最適化」を取り除くことを強くお勧めします。これにより、できるだけ単純なコードを書くよりもはるかに複雑で遅くなります。

LINQ to SQL (または LINQ to EF) で 1 回の呼び出しで複数のクエリを実行する方法はわかりませんが、このアプローチでは確実に実行できません。

この場合は関係ありませんが、LINQ to Objects で役立つ可能性のあるもう 1 つの小さなヒント - コレクションにデータがあるかどうかを調べたい場合は、Any()代わりに使用してください - そうすれば、Count() > 0何かが見つかったらすぐに停止できます。 .

于 2009-10-30T08:06:57.157 に答える