-1

次の linq クエリがあります。

var itembind = (from q in dsSerach.Tables[0].AsEnumerable()
            select new
                           {
                               PatternID = q.Field<int>("PatternID"),
                               PatternName = q.Field<string>("PatternName") + " " + q.Field<string>("ColorID") + q.Field<string>("BookID"),
                               ColorID = q.Field<string>("ColorID"),
                               BookID = q.Field<string>("BookID"),
                               CoverImage = (from img1 in objJFEntities.ProductImages.ToList()
                                             where img1.PatternName.ToLower() == q.Field<string>("PatternName").ToLower()
                                             select new CoverImage
                                             {
                                                 URL = "Images/MediumPatternImages/" +
                                                     q.Field<string>("PatternName") + "_" + q.Field<string>("ColorID") + q.Field<string>("BookID") + q.Field<string>("ImageExtension"),
                                                 ID = q.Field<int>("ProductImageID")
                                             }).FirstOrDefault(),
                               TotalCount = q.Field<int>("TotalCount")
                           }).Distinct();



var patterns = (from r in itembind
            group r by new { r.PatternID, r.ColorID } into g
            select new SearchPattern
            {
                PatternID = g.Key.PatternID,
                PatternName = string.Join(",", g.OrderBy(s => s.ColorID).OrderBy(s => s.BookID)
                                          .Select(s => String.Format("<a href='{0:s}' title='{1:s}'>{2:s}</a><br />",
                                                     new object[] { String.Format("Product.aspx?ID={0}&img={1}", g.Key.PatternID, s.CoverImage.ID), s.PatternName, s.PatternName })).FirstOrDefault()),
                CoverImage = g.Count() > 1 ? (from img1 in objJFEntities.ProductImages.ToList()
                                              where img1.ProductImageID == g.Select(i => i.CoverImage.ID).FirstOrDefault() && img1.ColorID.ToString() == g.Key.ColorID

                                              select new CoverImage
                                              {
                                                  URL = "Images/MediumPatternImages/" +
                                                      img1.PatternName + "_" + img1.ColorID + img1.BookID + img1.ImageExtension,
                                                  ID = img1.ProductImageID
                                              }).FirstOrDefault() : g.Select(i => i.CoverImage).FirstOrDefault()


            }).ToList();

これらのクエリは、1000 レコードのみを実行するのに 1 分以上かかります。dsSearch は、SQL のプロシージャから返されたレコードで満たされたデータセットです。エンティティ フレームワークを使用しています。サイトは IIS7.0 で展開されています。SQL サーバー 2008 が使用されています。

エラー メッセージ: タイムアウトが期限切れになりました。操作が完了する前にタイムアウト時間が経過したか、サーバーが応答していません。」、「ログインによって要求されたデータベース "DB" を開けません。ログインに失敗しました。」& "基になるプロバイダーが Open で失敗しました。" 非常に頻繁にエラーの種類のサイト。

このようなクエリを最適化する方法を教えてください。

編集:

手順はこちら

http://pastie.org/7160934

4

2 に答える 2

3

最初のクエリでは、 objJFEntities.ProductImages.ToList() を実行し、 ToList() 呼び出しを使用してデータベースからすべてのエントリを取得し、後でメモリ内の結果をフィルター処理します。

于 2013-03-29T12:46:48.690 に答える
2

問題の原因を指摘する Rolfvm は正しいですobjJFEntities.ProductImagesが、分析は少し異なります。クエリを列挙するときに、クエリの反復ごとProductImagesにテーブル全体をメモリにフェッチします。したがって、最適化の 1 つは、コレクション内の最初に画像をフェッチし、そのコレクションをクエリ ステートメントで使用することです。

var localImages = objJFEntities.ProductImages.ToList();
...
CoverImage = (from img1 in localImages....

しかし、あなたのクエリはやりすぎのようです。itembind最初の部分を実行せずにビルドします。次に、2 番目の部分 ( ) をビルドし、var patterns = (from r in itembindで実行しToList()ます。しかし、2 番目の部分ではCoverImage、最初の部分の を使用することはありません。したがって、これらを作成することはリソースの無駄です。(または、最初の部分の別の使用を隠して、コードをざっと読みました)。

于 2013-03-29T20:37:43.033 に答える