Frage

Ich bin neu in NHibernate und ich versuche zu lernen, wie meine Daten abgefragt werden.

Im Folgenden finden Sie die XML-Konfigurations. Nur das Rezept angezeigt wird.

Ich möchte in der Lage sein, Rezepte zur Abfrage von RecipeTitle von Keywords eingegeben und auch Zutaten aus ingredientname.

So Du "Pasta Wein" zum Beispiel eingeben.

Das ist, was ich versucht habe, aber ist mir ein Fehler.

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

Ich mag eifrig Last als auch die Sammlungen.

Bin ich etwa richtig abfragt ?? Ich muß in der Lage, den Query-String aus meinen Suchkriterien bauen. Dies würde mich einfach bildet in 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>
War es hilfreich?

Lösung

dynamische Abfragen zu erstellen, würde ich die Kriterien API verwenden. Dies macht die dynamische Abfrage wesentlich stabiler, weil Sie es nicht String-Operationen müssen aufzubauen.

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:

Für eifrigen Laden Sie den Fetch-Modus einstellen könnten:

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

Aber ich würde das nicht tun , weil Sie die Ergebnisse durch die Anzahl der Bilder, Kommentare und Zutaten multipliziert bekommen. Also, wenn Sie 4 Bilder haben, 2 Kommentare und 12 Zutaten, können Sie Ihr Rezept 96 mal bekommen. Sie erkennen dies nicht, weil NHibernate die Dinge wieder zusammen bringt, aber es erzeugt Verkehr zwischen der Anwendung und der Datenbank. Also besser lassen NHibernate laden Sie es mit separaten Abfragen.


Ein weiteres bearbeiten dynamische Abfrage Zusammensetzung zeigen.

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

Andere Tipps

Sowohl Stefan und Sathish der Beispiele verketten% Operatoren in die SQL. Dies ist als unnötiges Restrictions.Like (nhib 2.0+) und Expression.Like (vor v2.0) 3 Parameter-Versionen mit einem MatchMode haben.

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

Volltextabfragen sind auch mit NHibernate Suche zur Verfügung. Siehe Ayende dem Beispiel für weitere Details.

Hier ist die oben genannten Kriterien mit dynamischen Keywords

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>();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top