2010-06-28 13 views
5

मैं NHibernate उपयोग कर रहा हूँ पर एक मापदंड के साथ तत्वों को पुनः प्राप्त करने NHibernate का उपयोग कैसे करें और मैं दो निम्नलिखित वर्ग है जो मेरी डेटाबेस स्कीमा को मैप है:एक सूची

public class A 
{ 
    public virtual int Id { get; set;} 
    public virtual List<B> MyList { get; set; } 
} 

public class B 
{ 
    public virtual int Id { get; set; } 
    public virtual DateTime Date { get; set; } 
    public virtual A FKtoA { get; set; } 
} 

मैं की सभी प्रविष्टियों को प्राप्त करना चाहेंगे तालिका ए जिसमें उनके माईलिस्ट संपत्ति के सभी तत्व किसी दिए गए मान से कम दिनांक के साथ होते हैं।

मैं इसे एक सुरुचिपूर्ण एनएचबेर्नेट वाक्यविन्यास के साथ कैसे कर सकता हूं?

उत्तर

1

मैं तुम्हें "सुरुचिपूर्ण" भाग देना है ... :-)

यह एक संभावित एचक्यूएल है। ध्यान दें कि आपकी हालत उलटा: "ए जिसमें उनकी माईलिस्ट संपत्ति के सभी तत्व किसी दिए गए मान से कम दिनांक के साथ हैं" की तलाश करने के बजाय, मैं "ए " की कोई भी उनके माईलिस्ट के तत्व नहीं ढूंढता दिनांक से अधिक या उसके बराबर संपत्ति के साथ संपत्ति "।

from A a 
where a not in 
     (select a1 
     from A a1, B b 
     where b.Date >= :date 
     and b in elements(a1.MyList)) 

उपयोग:

var results = session.CreateQuery("hql from above") 
        .SetParameter("date", DateTime.Today) 
        .List(); 

ध्यान दें कि, यदि आप A और B जो द्विदिश रिश्ते की घोषणा (एक A संपत्ति जोड़कर), क्वेरी बहुत सरल है:

from A a 
where a not in 
     (select b.A 
     from B b 
     where b.Date >= :date) 

अद्यतन: यहां मानदंड के साथ इसे कैसे करें:

session.CreateCriteria<A>().Add(
    Subqueries.PropertyNotIn("id", 
          DetachedCriteria.For<A>() 
           .CreateCriteria("MyList") 
           .SetProjection(Projections.Property("id")) 
           .Add(Restrictions.Ge("Date", DateTime.Today)))) 
+0

द्विपक्षीय संबंधों के लिए अच्छा बिंदु: मैं अपनी कक्षा बी में टाइप ए की एक संपत्ति जोड़ूंगा। एचक्यूएल बहुत अच्छा है, लेकिन मैं सोच रहा था कि क्या हम डिटेक्टेडक्रिटिया() और अनुमानों के साथ sth नहीं प्राप्त कर सकते हैं। मैक्स() विधियों – PierrOz

+0

ठीक है, मैंने मानदंड विकल्प जोड़ा (इसे लेना मुश्किल नहीं होगा और इसे 'Subqueries.PropertyIn'' का उपयोग करने के लिए बदलना होगा और प्रक्षेपण का उपयोग करने के लिए उपखंड को उलटा करना होगा)। हालांकि, मानदंड गतिशील रूप से निर्मित प्रश्नों (खोज) के लिए मानदंड अधिक उपयोगी है। एचक्यूएल की तुलना में सभी शोर को देखो। –

+1

बहुत बढ़िया धन्यवाद !! – PierrOz

0

उपयोग इस

ICriteria criteria = session.CreateCriteria<ClassOfTableOne>(); 
criteria.CreateAlias("FieldNameOfTypeTable2","aliasName"); 
criteria.SetFetchMode("aliasName", FetchMode.Join); 
criteria.Add(Restrictions.Lt("aliasName.Date", yourdate)); 
+0

वह क्वेरी वापस नहीं लौटती जो PierrOz की अपेक्षा कर रही है। –

0

अपनी कक्षा बी कुछ इस तरह (जहां एक की MyList संपत्ति इस FK के लिए लग रहा है)

public class B 
{ 
    public virtual int Id { get; set; } 
    public virtual DateTime Date { get; set; } 
    public virtual A FK_ToA { get; set; } 
} 

तो मुझे लगता है कि आप देख रहे हैं लग रहा है अगर (HQL)

nhSes.CreateQuery("select b.FK_ToA from B b where b.Date < :passedDate") 
    .SetTimestamp("passedDate", DateTime.Now).List<A>() 
-1

वर्तमान में स्वीकृत उत्तर एक सहसंबंधित उप-क्वेरी पर निर्भर करता है, जो कि नियम-थंब के रूप में केवल "खराब SQL" है।

अधिक कार्यात्मक दृष्टिकोण की बजाय सेट आधारित अर्थशास्त्र का उपयोग करके इसे व्यक्त करना बेहतर है।

SELECT 
A.Id 
FROM A 
LEFT OUTER JOIN B ON A.Id = B.FKtoA 
WHERE B.Date < @MyDate 

यह पढ़ता है "के रूप में मैं एक के रूप में बी का एक सेट जहां बी की दिनांक कुछ मूल्य से भी कम है से संबंधित से कॉलम का समूह चाहते हैं":

अनिवार्य रूप से आप अपने एसक्यूएल इस तरह दिखना चाहते हैं। यह ICriteria एपीआई का उपयोग कर प्राप्त किया जा सकता:

ICriteria criteria = session.CreateCriteria<A>(); 
criteria.CreateAlias("MyList", "b", JoinType.LeftOuterJoin) 
criteria.Add(Restrictions.Lt("b.Date", myDate)); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
criteria.List<A>(); 

चाल का उपयोग कर रहा है के भाग NHibernate के अंतर्निहित DistinctRootEntityResultTransformer: के बाद से बाईं बाहरी में शामिल होने के बी प्रति एक से अधिक इंस्टेंस लौटा सकता है, हम केवल वापस जाने के लिए हमारे ICriteria चाहते विशिष्ट उदाहरण (मानते हैं कि हमें ऑर्डर करने या अन्य चीज़ों की परवाह नहीं है)।

+0

मेरा सुझाव है कि आप कुछ कठिन तथ्यों के साथ अपने "अंगूठे के नियम" वापस लें। इसके अलावा, आपका सुझाए गए एसक्यूएल काम नहीं करेगा: WHERE कथन में बी का उपयोग करके यह एक आंतरिक जुड़ाव बनता है (वही आपके मानदंड के साथ होता है, जिसमें क्लाइंट-साइड विशिष्ट ट्रांसफॉर्मर का अतिरिक्त बोझ होता है) –

+0

इससे आंतरिक शामिल नहीं होगा जैसा कि मैंने इसे बाहरी-शामिल के रूप में निर्दिष्ट किया है। आप इसे प्रोफाइलर के माध्यम से सत्यापित कर सकते हैं। अनिवार्य रूप से समस्या के दो दृष्टिकोण हैं: एक प्रश्न (जो समाधान मैंने सुझाया है) या दो प्रश्न (या तो एक सहसंबंधित उप-क्वेरी या दो पूरी तरह से अलग प्रश्नों के माध्यम से)। दोनों के पास पेशेवर/विपक्ष है। आपने एक ही प्रश्न के लिए प्राथमिक नुकसान का उल्लेख किया है। सहसंबंधित उप-क्वेरी के मामले में, इसे जांचें: http://stackoverflow.com/questions/141278/subqueries-vs-joins –

+0

जॉइन स्थिति के बाहर एक फ़िल्टर इसे एक आंतरिक जुड़ने में बदल देता है (* इसे आजमाएं *) । आप इसे एचक्यूएल (इन क्लॉज का उपयोग करके) के साथ जुड़ने की स्थिति का हिस्सा बना सकते हैं लेकिन मानदंड के साथ नहीं। इसके अलावा: इस मामले में सबक्वायरी सहसंबंधित नहीं है (मैं आंतरिक अंदर के बाहरी क्वेरी के तत्वों का उपयोग नहीं कर रहा हूं), इसलिए यह कम से कम सभ्य डीबी इंजनों के साथ जुड़ने के बराबर है। –

संबंधित मुद्दे