سؤال

لدي كيان "عقار"، وهذا الكيان لديه مجموعة "EstateFeatures"(النوع:EstateFeature) وEstateFeature لديه خاصية "MyFeatureValue".

ملحوظة:هذه هي الخصائص المحدودة للسؤال.جميع الكيانات لديها معرف وكل ما يلزم وما إلى ذلك

ملكية

IList<EstateFeature> EstateFeatures;

ميزة العقارات

FeatureValue MyFeatureValue;

قيمة الميزة

public virtual long Id;

أحاول الحصول على العقارات التي لها معرف الميزة المحدد

DetachedCriteria query = DetachedCriteria.For<Estate>();
Conjunction and = new Conjuction();
foreach (var id in idCollection)
   and.Add(Expression.Eq("MyFeatureValue.Id",id);

query
     .CreateCriteria("EstateFeatures")
     .Add(and);
IList<Estate> estates = query.GetExecutableCriteria(session).List<Estate>();

لم يتم إرجاع أي شيء من هذا الاستعلام، هل أفعل شيئًا خاطئًا؟

شكرًا

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

المحلول

سوف تحتاج إلى التأكد من انضمامك إلى MyFeatureValue مرة واحدة لكل ميزة تريد أن تمتلكها عقاراتك.

إحدى الطرق هي استدعاء .CreateAlias ​​لكل تكرار، وإعطائه اسمًا مستعارًا فريدًا ثم إضافة التعبير "aliasX.Id"

foreach (var id in idCollection)
{
   query = query.CreateAlias("MyFeatureValue", "feature" + id)
                .Add(Expression.Eq("feature" + id + ".Id",id);


}

لا أتذكر حقًا كيف يسير بناء الجملة، لقد كتبت هذا من رأسي، لست متأكدًا مما إذا كنت بحاجة إلى إعادة تعريف الاستعلام أيضًا :)

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

يحرر:نظرًا لوجود خطأ في Criteria API يمنعك من ربط مجموعة عدة مرات باستخدام CreateAlias ​​أو CreateCriteria، فأنت بحاجة إلى اللجوء إلى HQL.

http://derek-says.blogspot.com/2008/06/duplicate-association-path-bug-in.html

(السبات يعاني من نفس المشكلة أيضًا)

select e   
FROM Estate AS e
INNER JOIN e.MyFeatureValue AS fv1
INNER JOIN e.MyFeatureValue AS fv2
WHERE fv1.Id = 3
   AND fv2.Id = 13

ستحتاج إلى إنشاء HQL ديناميكيًا بحيث تصبح الأسماء المستعارة الخاصة بك فريدة (fv1، fv2، fvX ...)

نصائح أخرى

إذا فهمت بشكل صحيح أعتقد أن شيئًا كهذا قد ينجح

CreateCriteria(typeof(Estate))
     .CreateAlias("EstateFeatures", "estatefeature")
     .Add(Restrictions.In("estatefeature.MyFeatureValue.Id", ids))
     .List<Estate>();

ما الاستعلام الذي أنشأه NHibernate لك؟يمكنك التحقق من ذلك باستخدام خاصية التكوين show_sql.

كما أرى استعلامك، فأنت تحاول الحصول على جميع العقارات التي تحتوي على مجموعة معينة من الميزات.أعتقد أن هذا سيؤدي إلى إنشاء استعلام يبدو

SELECT ....
FROM Estates
INNER JOIN Features
WHERE Feature.Id = 1 AND Feature.Id = 2 ...

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

يبدو الرمز وكأنك تقوم بتمرير قائمة FeaturesValueIds وتريد قائمة تحتوي على كل هذه الميزات.إذا كان الأمر كذلك، فسألقي نظرة على SQL الذي تم إنشاؤه، وقم بتشغيله على قاعدة البيانات لمعرفة ما إذا كان يجب عليك استعادة أي شيء.

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

    exec sp_executesql N'SELECT TOP 3 id11_1_, Address11_1_, Title11_1_, Descript4_11_1_, 
    Price11_1_, Discount11_1_, ForBankL7_11_1_, AddDate11_1_, LastUpdate11_1_, 
IsVisible11_1_, ViewCount11_1_, SaleOrRent11_1_, LocationId11_1_, StaffId11_1_, 
CategoryId11_1_, id27_0_, EstateId27_0_, FeatureV3_27_0_ FROM (SELECT ROW_NUMBER() 
OVER(ORDER BY __hibernate_sort_expr_0__) as row, query.id11_1_, query.Address11_1_, 
query.Title11_1_, query.Descript4_11_1_, query.Price11_1_, query.Discount11_1_, 
query.ForBankL7_11_1_, query.AddDate11_1_, query.LastUpdate11_1_, query.IsVisible11_1_, 
query.ViewCount11_1_, query.SaleOrRent11_1_, query.LocationId11_1_, query.StaffId11_1_, 
query.CategoryId11_1_, query.id27_0_, query.EstateId27_0_, query.FeatureV3_27_0_, 
query.__hibernate_sort_expr_0__ FROM (SELECT this_.id as id11_1_, this_.Address as 
Address11_1_, this_.Title as Title11_1_, this_.Description as Descript4_11_1_, this_.Price 
as Price11_1_, this_.Discount as Discount11_1_, this_.ForBankLoan as ForBankL7_11_1_, 
this_.AddDate as AddDate11_1_, this_.LastUpdate as LastUpdate11_1_, this_.IsVisible as 
IsVisible11_1_, this_.ViewCount as ViewCount11_1_, this_.SaleOrRent as SaleOrRent11_1_, 
this_.LocationId as LocationId11_1_, this_.StaffId as StaffId11_1_, this_.CategoryId as 
CategoryId11_1_, estatefeat1_.id as id27_0_, estatefeat1_.EstateId as EstateId27_0_, 
estatefeat1_.FeatureValueId as FeatureV3_27_0_, CURRENT_TIMESTAMP as 
__hibernate_sort_expr_0__ FROM Estate this_ inner join EstateFeature estatefeat1_ on 
this_.id=estatefeat1_.EstateId WHERE this_.CategoryId = @p0 and 
(estatefeat1_.FeatureValueId = @p1 and estatefeat1_.FeatureValueId = @p2 and 
estatefeat1_.FeatureValueId = @p3 and estatefeat1_.FeatureValueId = @p4 and 
estatefeat1_.FeatureValueId = @p5 and estatefeat1_.FeatureValueId = @p6 and 
estatefeat1_.FeatureValueId = @p7)) query ) page WHERE page.row > 0 ORDER BY 
__hibernate_sort_expr_0__',N'@p0 bigint,@p1 bigint,@p2 bigint,@p3 bigint,@p4 bigint,@p5 
bigint,@p6 bigint,@p7 bigint',@p0=3,@p1=7,@p2=8,@p3=9,@p4=10,@p5=11,@p6=12,@p7=16

يبدو أنك تريد or (Disjunction) بدلاً من and (Conjunction).الآن أنت تبحث عنه EstateFeatureكائنات بحيث يكون لكل كائن عدة أشياء مختلفة Ids، والذي يبدو أنه ليس ما تريده.

var or = new Disjunction();
foreach(var id in idCollection)
    or.Add(Expression.Eq("MyFeatureValue.Id", id);

var query = DetachedCriteria.For<Estate>();
query
    .CreateCriteria("EstateFeatures")
    .Add(and);
var estates = query.GetExecutableCriteria(session).List<Estate>();

لقد جربت هذا أيضًا ولكن النتيجة واحدة:

DetachedCriteria features = DetachedCriteria.For<FeatureValue>();
features.SetProjection(Projections.Property("Id"));
features.Add(Property.ForName("Id").EqProperty("value.Id"));

var and = new Conjunction();

foreach (var l in FeatureIdCollection)
    and.Add(Expression.Eq("Id", l));

features.Add(and);

query.CreateCriteria("EstateFeatures")
     .CreateCriteria("MyFeatureValue","value")
     .Add(Subqueries.Exists(features));
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top