2009-05-08 26 views
7

Tôi mới dùng NHibernate và tôi đang cố gắng tìm hiểu cách truy vấn dữ liệu của mình.Truy vấn với NHibernate

Dưới đây là cấu hình xml. Chỉ có công thức được hiển thị.

Tôi muốn có thể truy vấn công thức nấu ăn theo đối tượng từ các từ khóa được nhập và cũng là thành phần từ tên thành phần.

Vì vậy, bạn có thể nhập "rượu pasta" chẳng hạn.

Đây là những gì tôi đã thử nhưng cho tôi lỗi.

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%'"; 

Tôi cũng muốn tải các bộ sưu tập.

Tôi có đang truy vấn đúng không ?? Tôi cần có khả năng tạo chuỗi truy vấn từ tiêu chí tìm kiếm của mình. Điều này sẽ dễ dàng hình thành tôi trong SQL.

Malcolm

<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> 

Trả lời

22

Để xây dựng các truy vấn năng động, tôi sẽ sử dụng API tiêu chí. Điều này làm cho truy vấn động ổn định hơn nhiều, bởi vì bạn không cần các hoạt động chuỗi để xây dựng nó.

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>(); 

Edit:

Nhằm giúp bạn tải háo hức bạn có thể thiết lập các chế độ lấy-:

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

Nhưng tôi sẽ không làm này bởi vì bạn sẽ có được kết quả nhân với số lượng hình ảnh, bình luận và thành phần. Vì vậy, nếu bạn có 4 Hình ảnh, 2 Bình luận và 12 Thành phần, bạn sẽ có được công thức 96 lần. Bạn không nhận ra điều này, bởi vì NHibernate đặt những thứ lại với nhau, nhưng nó tạo ra lưu lượng giữa ứng dụng và cơ sở dữ liệu. Vì vậy, tốt hơn cho NHibernate tải nó với các truy vấn riêng biệt.


hơn Một chỉnh sửa để hiển thị phần truy vấn năng động.

// 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

Để giải quyết vấn đề này, bạn có thể lấy DistinctRootEntityResultTransformer –

+0

Tại sao bạn sử dụng FetchMode.Join thay vì FetchMode.Eager cho những tải này nếu bạn thực sự có ý định sử dụng các đối tượng con? –

+0

Tôi không thấy nó hoạt động như thế nào khi bạn đã mã hóa từ khóa.Làm thế nào bạn sẽ truy vấn nếu tôi đã cho bạn một chuỗi các từ tách ra bởi không gian ??? – Malcolm

1

Dưới đây là các tiêu chí trên với từ khoá động

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

Cả Stefan và các ví dụ Sathish của concatenate% nhà khai thác vào SQL. Điều này là không cần thiết như Restrictions.Like (nhib 2.0+) và Expression.Like (trước v2.0) có 3 tham số phiên bản với một MatchMode.

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)); 
} 

Truy vấn văn bản đầy đủ cũng khả dụng với NHibernate Search. Xem Ayende's example để biết thêm chi tiết.

Các vấn đề liên quan