إضافة الإسقاط إلى معايير NHibernate تتوقف عن أداء اختيار الكيان الافتراضي

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

سؤال

وأنا أكتب على معايير NHibernate أن يختار بيانات الترحيل الداعمة. أنا باستخدام التعبير COUNT(*) OVER() من SQL Server 2005 (+) للحصول على عقد من إجمالي عدد الصفوف المتاحة، و<لأ href = "http://ayende.com/Blog/archive/2007/04/27/Paged داتا - العد مع NHibernate-وway.aspx-حقا سهلة "يختلط =" noreferrer "> اقترح التي كتبها Ayende Rahien. أنا بحاجة إلى أن عدد لتكون قادرة على حساب عدد الصفحات هناك في المجموع. جمال هذا الحل هو أنني لا تحتاج إلى تنفيذ استعلام الثاني للحصول على عقد من عدد الصفوف.

ولكن، وأنا لا يمكن أن يبدو لإدارة لكتابة معايير العمل (يوفر Ayende فقط استعلام HQL).

إليك استعلام SQL التي تظهر ما أريد، وأنه يعمل على ما يرام. لاحظ أن تركت عمدا خارج منطق الترحيل الفعلي للتركيز على المشكلة:

SELECT Items.*, COUNT(*) OVER() AS rowcount
FROM Items

وهنا يكمن HQL:

select
    item, rowcount()
from 
    Item item

لاحظ أن الدالة rowcount() مسجلة في العرف NHibernate لهجة وتعقد العزم على COUNT(*) OVER() في SQL.

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

var query = Session
    .CreateCriteria<Item>("item")
    .SetProjection(
       Projections.SqlFunction("rowcount", NHibernateUtil.Int32));

وكلما إضافة الإسقاط، NHibernate لم تقم بتحديد item (مثل أنه سيكون دون إسقاط)، فقط rowcount() بينما كنت حقا بحاجة على حد سواء. أيضا، وأنا لا يمكن أن يبدو لitem المشروع ككل، إلا أنها خصائص وأنا حقا لا أريد أن قائمة كل منهم.

وآمل شخص لديه حل لهذه. على أي حال شكرا.

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

المحلول

وأعتقد أنه ليس من الممكن في المعايير، ولديها بعض القيود.

هل يمكن الحصول على هذه البنود الهوية والحمل في استعلام لاحقا:

var query = Session
    .CreateCriteria<Item>("item")
    .SetProjection(Projections.ProjectionList()
       .Add(Projections.SqlFunction("rowcount", NHibernateUtil.Int32))
       .Add(Projections.Id()));

إذا كنت لا ترغب في ذلك، استخدم HQL، يمكنك تعيين العدد الأقصى من النتائج هناك أيضا:

IList<Item> result = Session
    .CreateQuery("select item, rowcount() from item where ..." )
    .SetMaxResult(100)
    .List<Item>();

نصائح أخرى

استخدم CreateMultiCriteria.

ويمكنك تنفيذ 2 بيانات بسيطة مع ضربة واحدة فقط إلى DB بهذه الطريقة.

وأنا أتساءل لماذا باستخدام معايير شرط. لا يمكنك استخدام session.CreateSQLQuery؟ إذا كنت حقا يجب أن تفعل ذلك في استعلام واحد، وأود أن اقترح الانسحاب الكائنات البند والفرز، مثل:

select {item.*}, count(*) over() 
from Item {item}

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

إذا فهمت سؤالك بشكل صحيح، لدي حل. أنا ناضلت لا بأس به مع هذه المشكلة نفسها.

واسمحوا لي بسرعة وصف مشكلة لدي، للتأكد من أننا على نفس الصفحة. وجاءت مشكلتي وصولا الى الترحيل. أريد أن عرض 10 السجلات في واجهة المستخدم، ولكن أريد أيضا أن أعرف <م> مجموعه عدد السجلات التي تطابق معايير التصفية. أردت أن إنجاز هذا باستخدام معايير API NH، ولكن عند إضافة الإسقاط لعدد الصفوف، الاستعلام بلدي لم يعد يعمل، وأنا لن تحصل على أية نتائج (لا أتذكر الخطأ محددة، ولكن هذا يبدو وكأنه ما 'إعادة الحصول على).

وهنا حل بلدي (نسخ ولصق من وجهة نظري رمز الإنتاج الحالي). لاحظ أن "SessionError" هو اسم كيان تجاري انا استرجاع البيانات المقسم إلى صفحات ل، وفقا ل3 مرشح المعيار: IsDev، IsRead، وIsResolved

ICriteria crit = CurrentSession.CreateCriteria(typeof (SessionError))
    .Add(Restrictions.Eq("WebApp", this));

if (isDev.HasValue)
    crit.Add(Restrictions.Eq("IsDev", isDev.Value));

if (isRead.HasValue)
    crit.Add(Restrictions.Eq("IsRead", isRead.Value));

if (isResolved.HasValue)
    crit.Add(Restrictions.Eq("IsResolved", isResolved.Value));

// Order by most recent
crit.AddOrder(Order.Desc("DateCreated"));

// Copy the ICriteria query to get a row count as well
ICriteria critCount = CriteriaTransformer.Clone(crit)
    .SetProjection(Projections.RowCountInt64());
critCount.Orders.Clear();

// NOW add the paging vars to the original query
crit = crit
    .SetMaxResults(pageSize)
    .SetFirstResult(pageNum_oneBased * pageSize);

// Set up a multi criteria to get your data in a single trip to the database
IMultiCriteria multCrit = CurrentSession.CreateMultiCriteria()
    .Add(crit)
    .Add(critCount);

// Get the results
IList results = multCrit.List();

List<SessionError> sessionErrors = new List<SessionError>();
foreach (SessionError sessErr in ((IList)results[0]))
    sessionErrors.Add(sessErr);

numResults = (long)((IList)results[1])[0];

وهكذا أنا خلق معايير قاعدة بلدي، مع فرض قيود اختيارية. ثم أنا استنساخ ذلك، وإضافة الإسقاط الصف العد للمعايير المستنسخة. علما بأنني استنساخ عليه <م> قبل I إضافة قيود الترحيل. ثم أقوم بإعداد وIMultiCriteria لاحتواء الكائنات ICriteria الأصلية والمستنسخة، واستخدام IMultiCriteria لتنفيذ كل منهما. الآن لدي البيانات المقسمة بلدي من ICriteria الأصلي (وأنا فقط سحب البيانات أحتاج عبر الأسلاك)، وأيضا عدد الخام لكيفية الملائمة العديد من السجلات الفعلية معايير بلدي (مفيدة للعرض أو إنشاء وصلات الترحيل، أو أيا كان). وقد عملت هذه الاستراتيجية بشكل جيد بالنسبة لي. آمل أن يكون هذا مفيدا.

وأود أن أقترح التحقيق نتيجة مخصص محول من خلال الدعوة SetResultTransformer () على جلسة العمل الخاصة بك.

إنشاء خاصية الصيغة في رسم الخرائط الدرجة:

<property name="TotalRecords" formula="count(*) over()" type="Int32" not-null="true"/>;

IList<...> result = criteria.SetFirstResult(skip).SetMaxResults(take).List<...>();
totalRecords = (result != null && result.Count > 0) ? result[0].TotalRecords : 0;
return result;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top