سؤال

أنا استخدم IQueryable<T> واجهات في جميع أنحاء تطبيقي وتأجيل تنفيذ SQL على DB حتى الأساليب مثل .ToList()

سأحتاج إلى العثور على عدد القوائم معينة أحيانا - دون الحاجة لاستخدام البيانات في القائمة التي يتم احتسابها. أعرف من تجربة SQL الخاصة بي أن عدد SQL () أقل بكثير من العمل DB من عبارة SELECT المكافئة التي ترجع جميع الصفوف.

لذلك سؤالي هو: هل سيكون أقل عمل في DB لإرجاع العد من IQueryable<T>Count() طريقة من تقديم IQueryable<T> إلى قائمة وإلغاء القائمة Count() طريقة؟

أظن أنه سوف يعطى أن ToList() سوف يطلق النار SQL SELECT SQL ثم في استعلام منفصل، عد الصفوف. آمل أن Count() على ال IQueryable<T> ببساطة يجعل SQL ل SQL Count () استعلام بدلا من ذلك. لكن أنا لست متأكدا. هل تعرف؟

هل كانت مفيدة؟

المحلول

دعا ToList() سوف تعيد حقيقية List<T> مع كل البيانات، مما يعني جلب جميع البيانات. ليست جيدة.

دعا Count() يجب أن تقدم SQL بالفعل للقيام بعدد في جانب قاعدة البيانات. أفضل بكثير.

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

نصائح أخرى

لست متأكدا مما إذا كانت قاعدة صعبة وسريعة، ولكن طريقة LINQ التي تضيفها إلى IQueryable ستتم إضافتها إلى شجرة التعبير LinQ - ما لم تكن واحدة من الأساليب التي تسبب تقييم الشجرة في الواقع (مثل Tolist وفرد إلخ). في حالة LINQTOSQL، ستعرف ما إذا كان لا يمكن تحويل شيء ما إلى عبارة SQL لأنك ستحصل على استثناء وقت التشغيل تفيد بأن الطريقة غير مدعومة.

على سبيل المثال

var something = dbContext.SomeTable
  .Select(c => c.col1 == "foo")
  .Distinct()
  .ToList()
  .Count()

في ما ورد أعلاه، يتم تضمين () ومميز () في استعلام SQL المرت إلى الخادم لأنه يتم إضافته إلى IQueryable. العد () يتصرف فقط في القائمة التي تم إرجاعها بواسطة استعلام SQL. لذلك أنت لا تريد أن تفعل ذلك بهذه الطريقة :-)

في قضيتك، ستكون Count () Count () بشكل أسرع تحديد () لأن عبارة SQL الناتجة ستدمج بالفعل العدد، لذلك يحتاج الخادم فقط إلى إرجاع رقم واحد بدلا من قائمة الصفوف.

إذا كنت تستخدم SQL Server، فلا يزال العد () مكلفا للغاية لأنه يؤدي إلى فحص جدول (أو مسح فهرس، راجع التعليقات على الإجابة الأساسية). و، من خلال LinQ الافتراضي لا يستخدم مستوى العزلة قراءة قراءة، مما يجعل الأمور أسوأ بسبب قفل.

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

/// <summary>A very fast method for counting rows in a table.</summary>
public static long FastRowCount(DataContext context, string tableName)
{
    const string template = "SELECT rowcnt FROM sys.sysindexes WHERE id = OBJECT_ID('{0}') AND indid < 2";
    string query = string.Format(template, tableName);
    return context.ExecuteQuery<long>(query).Single();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top