2009-05-08 15 views
7

के साथ पूछताछ मैं NHibernate के लिए नया हूं और मैं अपने डेटा से पूछताछ करने के तरीके सीखने की कोशिश कर रहा हूं।NHibernate

नीचे कॉन्फ़िगरेशन xml है। केवल नुस्खा दिखाया गया है।

मैं दर्ज किए गए कीवर्ड से व्यंजनों से व्यंजनों से पूछताछ करना चाहता हूं और घटक नाम से सामग्री भी प्राप्त करना चाहता हूं।

तो उदाहरण के लिए आप "पास्ता शराब" दर्ज कर सकते हैं।

यही मैंने कोशिश की है लेकिन मुझे एक त्रुटि देता है।

hql = "from Recipe r " + 
    "left join r.Images " + 
    "inner join r.User " + 
    "inner join r.Ingredients i " + 
    "where i.IngredientName Like '%pasta%' OR i.IngredientName Like '%wine%' OR r.RecipeTitle Like '%pasta' OR r.RecipeTitle Like '%wine%'"; 

मैं संग्रह को भी लोड करना चाहता हूं।

क्या मैं सही पूछताछ के बारे में जा रहा हूं ?? मुझे अपने खोज मानदंडों से क्वेरी स्ट्रिंग बनाने में सक्षम होना चाहिए। एसक्यूएल में यह आसान फॉर्म होगा।

मैल्कम

<class name="Recipe" table="Recipes" xmlns="urn:nhibernate-mapping-2.2"> 
    <id name="RecipeID" type="Int32" column="RecipeID"> 
     <generator class="identity" /> 
    </id> 
    <property name="RecipeTitle" type="String"> 
     <column name="RecipeTitle" /> 
    </property> 
    <property name="Completed" type="Boolean"> 
     <column name="Completed" /> 
    </property> 
    <property name="ModifiedOn" type="DateTime"> 
     <column name="ModifiedOn" /> 
    </property> 
    <property name="Rating" type="Double"> 
     <column name="Rating" /> 
    </property> 
    <property name="PrepTime" type="Int32"> 
     <column name="PrepTime" /> 
    </property> 
    <property name="CookTime" type="Int32"> 
     <column name="CookTime" /> 
    </property> 
    <property name="Method" type="String"> 
     <column name="Method" /> 
    </property> 
    <bag name="Images" inverse="true" cascade="all"> 
     <key column="RecipeID" /> 
     <one-to-many class="OurRecipes.Domain.RecipeImage, OurRecipes.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
    <many-to-one name="Category" column="CategoryID" /> 
    <bag name="Comments" inverse="true" cascade="all"> 
     <key column="RecipeID" /> 
     <one-to-many class="OurRecipes.Domain.Comment, OurRecipes.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
    <many-to-one name="User" column="EnteredByID" /> 
    <bag name="Ingredients" inverse="true" cascade="all"> 
     <key column="RecipeID" /> 
     <one-to-many class="OurRecipes.Domain.Ingredient, OurRecipes.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
    </class> 

उत्तर

22

गतिशील प्रश्नों का निर्माण करने के लिए, मैं मापदंड एपीआई का प्रयोग करेंगे। इससे डायनामिक क्वेरी अधिक स्थिर हो जाती है, क्योंकि इसे बनाने के लिए आपको स्ट्रिंग ऑपरेशंस की आवश्यकता नहीं होती है।

ICriteria query = Session.CreateCriteria(typeof(Recipe), "r") 
    .CreateCriteria("Ingredients", "i", JoinType.InnerJoin) 
    .Add(
    Expression.Disjunction() // OR 
     .Add(Expression.Like("i.IngredientName", "%pasta%")) 
     .Add(Expression.Like("i.IngredientName", "%wine%")) 
     .Add(Expression.Like("r.RecipeTitle", "%pasta%")) 
     .Add(Expression.Like("r.RecipeTitle", "%wine%"))); 

List<Recipe> result = query.List<Recipe>(); 

संपादित करें:

उत्सुक लोड हो रहा है के लिए आप लाने के मोड सेट कर सकते हैं:

ICriteria query = Session.CreateCriteria(typeof(Recipe), "r") 
    .SetFetchMode("Images", FetchMode.Join) 
    .SetFetchMode("Comments", FetchMode.Join) 
    .SetFetchMode("Ingredients", FetchMode.Join) 

लेकिन मैं इस ऐसा नहीं करेंगे क्योंकि आप से गुणा परिणाम प्राप्त छवियों की संख्या, टिप्पणियां और सामग्री। तो अगर आपके पास 4 छवियां, 2 टिप्पणियाँ और 12 सामग्री थीं, तो आपको अपना नुस्खा 96 बार मिलता है। आप इसे पहचान नहीं पाते हैं, क्योंकि NHibernate चीजों को एक साथ फिर से रखता है, लेकिन यह एप्लिकेशन और डेटाबेस के बीच यातायात उत्पन्न करता है। इतना बेहतर है कि NHibernate इसे अलग-अलग प्रश्नों से लोड करें।


एक और संपादित गतिशील क्वेरी रचना दिखाने के लिए।

// filter arguments, all are optional and should be omitted if null 
List<string> keywords; 
TimeSpan? minCookingTime; 
TimeSpan? maxCookingTime; 
int? minRating; 
int? maxRating; 

ICriteria query = Session.CreateCriteria(typeof(Recipe), "r"); 

if (keyword != null) 
{ 
    // optional join 
    query.CreateCriteria("Ingredients", "i", JoinType.InnerJoin); 

    // add keyword search on ingredientName and RecipeTitle 
    var disjunction = Expression.Disjunction(); 
    foreach (string keyword in keywords) 
    { 
    string pattern = String.Format("%{0}%", keyword); 
    disjunction 
     .Add(Expression.Like("i.IngredientName", pattern)) 
     .Add(Expression.Like("r.RecipeTitle", pattern)); 
    } 
    query.Add(disjunction) 
} 

if (minCookingTime != null) 
{ 
    query.Add(Expression.Ge(r.CookingTime, minCookingTime.Value)); 
} 
if (maxCookingTime != null) 
{ 
    query.Add(Expression.Le(r.CookingTime, maxCookingTime.Value)); 
} 

if (minRating != null) 
{ 
    query.Add(Expression.Ge(r.Rating, minRating.Value)); 
} 
if (maxRating != null) 
{ 
    query.Add(Expression.Le(r.Rating, maxRating.Value)); 
} 
+0

इस समस्या को हल करने के लिए, आप DistinctRootEntityResultTransformer –

+0

प्राप्त कर सकते हैं आप FetchMode.Join के बजाय FetchMode.Join का उपयोग क्यों करेंगे यदि आप वास्तव में बाल वस्तुओं का उपयोग करने का इरादा रखते हैं? –

+0

मुझे नहीं लगता कि जब आप कीवर्ड को हार्ड कोड करते हैं तो यह गतिशील कैसे होता है।यदि आप रिक्त स्थान से अलग शब्दों की एक स्ट्रिंग देते हैं तो आप कैसे पूछेंगे ??? – Malcolm

1

डायनामिक कीवर्ड

string searchQuery = "wine pasta"; 

ICriteria query = Session.CreateCriteria(typeof(Recipe), "r") 
        .CreateCriteria("Ingredients", "i", JoinType.InnerJoin) 
        .SetFetchMode("Images", FetchMode.Join) 
        .SetFetchMode("Comments", FetchMode.Join) 
        .SetFetchMode("Ingredients", FetchMode.Join) 
        .SetResultTransformer(new DistinctRootEntityResultTransformer()); 

var keywords = searchQuery.Split(' '); 

Disjunction keywordsCriteria = Restrictions.Disjunction(); 
foreach (var keyword in keywords) 
{ 
    keywordsCriteria.Add(Restrictions.Like("i.IngredientName", string.Format("%{0}%", keyword))); 
    keywordsCriteria.Add(Restrictions.Like("r.RecipeTitle", string.Format("%{0}%", keyword))); 
} 

query.Add(keywordsCriteria); 

List<Recipe> result = query.List<Recipe>(); 
5

दोनों स्टीफन की और सतीश के उदाहरण SQL में% ऑपरेटरों को श्रेणीबद्ध साथ उपरोक्त मानदंडों है। यह प्रतिबंधों के रूप में अनावश्यक है। जैसे (nhib 2.0+) और अभिव्यक्ति। जैसा (v2.0 से पहले) में MatchMode के साथ 3 पैरामीटर संस्करण हैं।

Disjunction keywordsCriteria = Restrictions.Disjunction(); 
foreach (var keyword in keywords) 
{ 
    keywordsCriteria.Add(Restrictions.Like("i.IngredientName", keyword, MatchMode.Anywhere)); 
    keywordsCriteria.Add(Restrictions.Like("r.RecipeTitle", keyword, MatchMode.Anywhere)); 
} 

पूर्ण पाठ प्रश्न NHibernate खोज के साथ भी उपलब्ध हैं। अधिक जानकारी के लिए Ayende's example देखें।