質問

ネットワークの待ち時間を避けるために、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!!
役に立ちましたか?

解決

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

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

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

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

LINQ to SQL(またはLINQ to EF)を使用して1回の呼び出しで複数のクエリを実行する方法はわかりませんが、この方法では実行できません。

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

他のヒント

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

System(Diagnostics.Stopwatch )を Count()の呼び出しの周りに配置し、表示されている時間の大部分を占めているかどうかを確認します。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top