المساعدة اللازمة لتحسين linq استخراج البيانات

StackOverflow https://stackoverflow.com/questions/1648512

  •  22-07-2019
  •  | 
  •  

سؤال

أنا جلب البيانات من جميع 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 إلى كائنات الاستعلام:انها مجرد العودة نتيجة الدعوة ent.Basket.Where(...).Select(...) الخ...التي لا فعلا تنفيذ الاستعلام.

الخطة الخاصة بك أن تفعل كل ثلاثة استفسارات في دفعة واحدة لا تعمل في الواقع.ومع ذلك, قبل طلب الاعتماد بشكل منفصل ، قد يكون في الواقع تنفيذ كل قاعدة بيانات الاستعلام مرتين - مرة واحدة فقط الحصول على الاعتماد ومرة النتائج.

أقترح بشدة أن تحصل على التخلص من "تحسينات" في هذه المدونة التي هي مما يجعلها أكثر تعقيدا من ذلك بكثير ، أبطأ من مجرد الكتابة أبسط كود يمكنك.

أنا لا أعرف أي طريقة للحصول على LINQ to SQL (أو ينق ل EF) لتنفيذ استعلامات متعددة في مكالمة واحدة - ولكن هذا النهج بالتأكيد لن تفعل ذلك.

واحد الطفيفة الأخرى التلميح الذي يهم في هذه الحالة ، ولكن يمكن أن تكون مفيدة في LINQ إلى الأشياء - إذا كنت ترغب في معرفة ما إذا كان هناك أية بيانات في مجموعة, مجرد استخدام Any() بدلا من Count() > 0 - أن هذه الطريقة يمكن أن تتوقف في أقرب وقت كما انها وجدت أي شيء.

نصائح أخرى

وإنك تستخدم IEnumerable في حلقة foreach. يكون التنفيذ فقط لإعداد البيانات عندما يكون طلب من أجله. وبهذه الطريقة، أنا أقترح أن رمز أعلاه يتم الوصول إلى البيانات الخاصة بك بتكاسل - وهذا هو، فقط عند تعداد العناصر

(الذي يحدث فعلا عند استدعاء Count()).

ووضع System.Diagnostics.Stopwatch حول الدعوة إلى Count() ومعرفة ما إذا كان هذا ما أخذ الجزء الأكبر من وقت ترونه.

لا أستطيع التعليق مزيد من هنا لأنك لم تحدد نوع ent في نموذج التعليمات البرمجية الخاصة بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top