NHibernate:过滤一对多联接的结果



我正试图根据左侧联接上所有对象的值来筛选查询。我的对象定义如下:

public class Recipe
{
public virtual long Id {get;set;}
public virtual ISet<Ingredient> Ingredients { get; set; } = new HashSet<Ingredient>();
}
public class Ingredient
{
public virtual long Id{get;set;}
public virtual string Ingredient {get;set;}
public virtual decimal Amount {get;set;}
}

它们是这样映射的:

<hibernate-mapping>
<class name="Recipe"  table="Recipe">
<set name="Ingredients" inverse="true">
<key column="RecipeId" />
<one-to-many class="Recipe" />
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="Ingredient" dynamic-update="true" table="Ingredient" lazy="false">
<id name="Id" column="Id" type="long" unsaved-value="0">
<generator class="native" />
</id>
<property name="Ingredient" not-null="true" lazy="false"/>
<property name= "Amount" column= "Amount" type="decimal" />    
</class>
</hibernate-mapping>

我想做的是能够根据配料搜索食谱。例如,我想找到所有成分都是的食谱

Ingredient | Amount
Sugar      |  100
Flour      |  200
Eggs       |    2

我真的不确定在SQL中该怎么做。我试过这样的东西:

public Recipe FindRecipeByIngredients(ISet<Ingredient> ingredients)
{
return this.Session.QueryOver<Recipe>()
.Where(r => r.Ingredients.All(c => ingredients.Any(i => i.Ingredient == r.Ingredient && i.Amount == r.ConcentrAmountation))).SingleOrDefault();
}

但是Nhibernate不知道如何将All转换为SQL。我想可以反过来搜索,在配料表中搜索所有含有正确配料和量的记录,但随后我会想出所有含有这些配料和其他配料的食谱。这可以使用SQL查询完成吗?还是我必须接受这样一个事实,即我必须提取所有记录(使用最少的过滤(,然后在代码中过滤它们?

(作为奖励,我还必须在未来筛选类似的食谱,因此数量几乎相等的食谱,所以可能数量<1.05refAmount;&amount>0.95refAmount(

好的,所以我设法找到了一个相当好的解决方案。我需要运行的sql查询是:

SELECT RecipeId
FROM Ingredient
GROUP BY RecipeId 
HAVING SUM(CASE WHEN Ingredient = 'Ingredient1'  AND Amount = 200 THEN 1 ELSE 0 END) = 1
AND SUM(CASE WHEN Ingredient = 'Ingredient2'  AND Amount = 300 THEN 1 ELSE 0 END) = 1
AND ...

我在将其转换为nhibernate可以正确构建的东西时遇到了一些问题,最终得到了这样的结果:

ICriteria criteria = Session.CreateCriteria<Ingredients>()
.SetProjection(Projections.GroupProperty(Projections.Property<Ingredient>(i => i.Recipe.Id)));
foreach (Ingredient ingredient in recipe.Ingredients)
{
criteria.Add(
Restrictions.Eq(
Projections.Sum(
Projections.Conditional(
Restrictions.Where<Ingredient>(i => i.Ingredient == ingredient.Ingredient && i.Amount == ingredient.Amount)
Projections.Constant(1),
Projections.Constant(0)
)
),
1));
}

返回上述查询。我尝试使用Restrictions.Conjuction或QueryOver进行查询,但条件查询最终出现在GROUP BY之前的WHERE条件中,而不是GROUP BY之后的HAVING条件中,导致sql查询不正确。这可能是Nhibernate中的一个错误(类似于NH-2863(,但我不确定。如果有人找到更有效的方法来解决这个问题,我很乐意更新它。答案也基于SO:上的这些答案

https://stackoverflow.com/a/24334034/5426336

https://stackoverflow.com/a/3556840/5426336

相关内容

  • 没有找到相关文章

最新更新