التحميل السريع للكيانات المحملة البطيئة في nHibernate باستخدام ActiveRecord

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

سؤال

أنا أعمل على مشروع يحتوي على نموذج كائن غني بمجموعات مختلفة من الجذور المجمعة.

نحن نستخدم قلعة المكدس (الخط المفرد حتى nHibernate باستخدام ActiveRecord).

لقد وضعنا علامة على الجذور الإجمالية على أنها كسولة [ActiveRecord(Lazy = true)] وقمنا بتخصيص إجراءات "حريصة" في مستودعنا لجلب رسم بياني للكائنات.نحن نستخدم HQL لتحديد عمليات الجلب المتلهفة من مجموعة الأطفال الخاصة بنا من جذرنا،

على سبيل المثاللو Account هو الجذر الكلي (والذي تم وضع علامة عليه كسول محمل) الذي سنجلبه بفارغ الصبر Account .. Order .. Product الكيانات للحصول على رسم بياني كامل.

لذلك لا توجد مفاجآت حتى الآن (نأمل).

الآن، إذا تم وضع علامة على المنتج أيضًا في المثال أعلاه [ActiveRecord(Lazy = true)], يبدو أن هذا يوقف توجيه الجلب المتلهف في HQL.

هل يعرف أحد طريقة لفرض الجلب المتلهف لكائن فرعي محمل كسولًا ??

هتاف إيان

تحديث:

حسنًا، إليك بعض أمثلة hql، باستخدام المثال من 'me.yahoo.com/../1' أدناه، نحن نستخدم IMuliQuery لإعادة تحديد تبعيات N+1 عند جلب علاقات متعدد إلى متعدد.نحن أيضًا نستخدم بشكل صريح فئات تعيين متعدد إلى متعدد.ونتيجة لذلك لدينا HQL هو:

from Account a 'm eager loading the graph
inner join fetch a.AccountsOrders ao 
inner join fetch ao.Order
from Account a 'm eager loading the graph
inner join fetch a.AccountAddresses aa
inner join fetch aa.Address ad
where a.ID = ?

...لذلك يؤدي هذا إلى تنفيذ عبارات 2 SQL وإرجاع الحد الأدنى المطلوب من مجموعة الصفوف، ويمكننا حل ذلك في رسم بياني لكائن واحد.لطيف - جيد.

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

فلماذا لا يتم تحميل الكيان الكسول Address, ، أعلاه، حريصة على جلب البيان أعلاه؟

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

المحلول

لماذا تريد السلوك المتحمس؟

تحتوي كافة سمات العلاقة في ActiveRecord على معلمة "Lazy=" لإخبار ActiveRecord بالتحميل البطيء للكائن ذي الصلة.الكل باستثناء BelongsTo.يتحقق BelongsTo مما إذا كان الكائن التابع يحتوي على Lazy=true في سمة ActiveRecord الخاصة به، ثم يقوم بإنشاء وكيل للكائن بدلاً من إجراء التحديد أو الانضمام.

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

الآن قد يبدو جلب الرسم البياني الكامل للأداء فكرة جيدة، لكن من الناحية العملية ربما يكون الأمر أبطأ.لدي 3 أسباب وجيهة لذلك:

1.) لدى BelongsTo خيار جلب لتحديد كيفية سحب الكائنات ذات الصلة.يفرض FetchEnum.Join على AR استخدام الانضمام.FetchEnum.تحديد يفرض AR لاستخدام عبارات تحديد منفصلة لكل كائن.عمليات الانضمام بطيئة، ونرى تحسنًا في الأداء بمقدار 10 أضعاف من التبديل إلى التحديدات الفردية.لا يوجد فرق فعال في كود العميل بين Lazy=true + FetchEnum.Select و حريص.

2.) يقوم NHibernate بالتخزين المؤقت.إذا تم بالفعل تخزين الكائن مؤقتًا في الجلسة أو في ذاكرة التخزين المؤقت للمستوى 2، فيمكن تحميله من هناك وتجنب العمل الإضافي.

3.) قد تفوتك أي فوائد للتحميل البطيء في الحالات التي لا تشير فيها إلى جزء من الرسم البياني للكائن.مرة أخرى سوف تقوم بعمل أكثر من اللازم.

نصائح أخرى

قم بإجراء "جلب صلة داخلية" على كيان Account.Order.Product.فبدلاً من شيء مثل هذا (والذي ربما يكون لديك بالفعل):

"from Account a inner join fetch a.Order where a.ID = ?"

اطلب منه إحضار الطلب.المنتج أيضًا:

"from Account a inner join fetch a.Order inner join fetch a.Order.Product where a.ID = ?"

من "NHibernate in Action"، الصفحة 225:

يحدك NHibernate حاليًا من جلب مجموعة واحدة فقط بفارغ الصبر.

قد يفسر ذلك الاستعلام الثاني لجلب العناوين.

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