سؤال

بالنظر إلى LINQ التالي لاستعلام SQL:

var test = from i in Imports
           where i.IsActive
           select i;

عبارة SQL المفسرة هي:

SELECT [t0].[id] AS [Id] .... FROM [Imports] AS [t0] WHERE [t0].[isActive] = 1

لنفترض أنني أردت تنفيذ بعض الإجراءات في التحديد والتي لا يمكن تحويلها إلى SQL.أفهم أن الطريقة التقليدية لتحقيق ذلك هي القيام بذلك AsEnumerable() وبالتالي تحويله إلى كائن عملي.

بالنظر إلى هذا الكود المحدث:

var test = from i in Imports.AsEnumerable()
           where i.IsActive
           select new 
           { 
               // Make some method call 
           };

وتحديث SQL:

SELECT [t0].[id] AS [Id] ... FROM [Imports] AS [t0] 

لاحظ عدم وجود جملة حيث في عبارة SQL المنفذة.

هل هذا يعني أنه تم تخزين جدول "الاستيرادات" بالكامل في الذاكرة مؤقتًا؟هل سيؤدي هذا إلى إبطاء الأداء على الإطلاق إذا كان الجدول يحتوي على كمية كبيرة من السجلات؟

ساعدني في فهم ما يحدث بالفعل خلف الكواليس هنا.

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

المحلول

السبب ل AsEnumerable هو

يمكن استخدام Asenumerable (tsource) (ienumerable (tsource)) للاختيار بين تطبيقات الاستعلام عندما يتنفس التسلسل

لذلك عندما كنت تتصل ب Where الطريقة السابقة، كنت تتصل بطريقة مختلفة Where الطريقة من IEnumerable.Where.الذي - التي Where كان البيان هو تحويل LINQ إلى SQL، الإصدار الجديد Where هل IEnumerable واحد يأخذ IEnumerable, ، يعدده وينتج العناصر المطابقة.وهو ما يفسر سبب ظهور SQL المختلفة التي يتم إنشاؤها.سيتم أخذ الجدول بالكامل من قاعدة البيانات قبل Where سيتم تطبيق الامتداد في الإصدار الثاني من الكود.قد يؤدي هذا إلى حدوث عنق زجاجة خطير، لأن الجدول بأكمله يجب أن يكون في الذاكرة، أو الأسوأ من ذلك أن الجدول بأكمله يجب أن ينتقل بين الخوادم.السماح لخادم SQL بتنفيذ Where وتفعل ما هو أفضل.

نصائح أخرى

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

حل جزء وجزء يمكن أن يكون الطريق.النظر في

giveacodicetagpre.

دعنا نقول أيضا أن nondatabaseconvertablecerion يتطلب حقل ج من النتيجة.لأن nondatabaseconvertabletraiterion هل يفعل ما يشير إليه اسمه، يجب إجراء هذا كعمدا.ومع ذلك، فكر في:

giveacodicetagpre.

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

هناك ثلاثة تطبيقات ل AsEnumerable.

DataTableExtensions.AsEnumerable

يمتد أ DataTable لإعطائها IEnumerable واجهة حتى تتمكن من استخدام Linq ضد DataTable.

Enumerable.AsEnumerable<TSource> و ParallelEnumerable.AsEnumerable<TSource>

ال AsEnumerable<TSource>(IEnumerable<TSource>) الطريقة ليس لها تأثير سوى تغيير نوع المصدر المترجمة من نوع ينفذ IEnumerable<T> ل IEnumerable<T> بحد ذاتها.

AsEnumerable<TSource>(IEnumerable<TSource>) يمكن استخدامها للاختيار بين تطبيقات الاستعلام عندما يتنفس التسلسل IEnumerable<T> ولكن لديه أيضًا مجموعة مختلفة من أساليب الاستعلام العامة المتاحة.على سبيل المثال، نظرا لفئة عامة Table الذي ينفذ IEnumerable<T> ولها أساليبها الخاصة مثل Where, Select, ، و SelectMany, ، دعوة ل Where سوف يستدعي الجمهور Where طريقة TableTable النوع الذي يمثل جدول قاعدة بيانات يمكن أن يحتوي على Where الطريقة التي تأخذ الوسيطة المسند كشجرة تعبير وتحول الشجرة إلى SQL للتنفيذ عن بُعد.إذا لم يكن التنفيذ عن بُعد مطلوبًا ، على سبيل المثال لأن المسند يستدعي طريقة محلية ، AsEnumerable<TSource> يمكن استخدام الطريقة لإخفاء الأساليب المخصصة وبدلاً من ذلك إتاحة مشغلي الاستعلام القياسي.

بعبارة أخرى.

إذا كان لدي

IQueryable<X> sequence = ...;

من LinqProvider، مثل Entity Framework، وأنا أفعل ذلك،

sequence.Where(x => SomeUnusualPredicate(x));

سيتم إنشاء هذا الاستعلام وتشغيله على الخادم.سيفشل هذا في وقت التشغيل لأن EntityFramework لا يعرف كيفية التحويل SomeUnusualPredicate إلى SQL.

إذا كنت أرغب في تشغيل العبارة باستخدام Linq to Objects بدلاً من ذلك، فأنا أفعل ذلك،

sequence.AsEnumerable().Where(x => SomeUnusualPredicate(x));

الآن سيقوم الخادم بإرجاع كافة البيانات و Enumerable.Where سيتم استخدام من Linq إلى الكائنات بدلاً من تنفيذ موفر الاستعلام.

لن يهم أن Entity Framework لا يعرف كيفية تفسيره SomeUnusualPredicate, ، سيتم استخدام وظيفتي مباشرة.(ومع ذلك، قد يكون هذا أسلوبًا غير فعال حيث سيتم إرجاع كافة الصفوف من الخادم.)

أعتقد أن Asenumerable يحكي فقط التحويل البرمجي الذي تمديد الأساليب لاستخدامه (في هذه الحالة يتم تعريفها ل Ienumerable بدلا من تلك الخاصة ب IQueryable). لا يزال تنفيذ الاستعلام مؤجلا حتى تتصل ب ToArray أو تعداد عليه.

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