4

亲爱的 NHibernate 专家,

以下查询为我提供了所有类别:

var result = Session.QueryOver(() => cat).List();

..并通过运行此查询,我选择了那些(category_x_product 表):

int productId = 11;
Category cat = null;
CategoryProduct cp = null;

var subQuery = QueryOver.Of(() => cp)
        .Where(() => cp.ProductId == productId)
        .Select(Projections.Distinct(Projections.Property(() => cp.CategoryId)));

result = Session.QueryOver(() => cat)
                .WithSubquery
                .WhereProperty(() => cat.Id).In(subQuery)
                .List();

组合这两个查询的任何方式,以便我获得所有类别的布尔值,指示在 CategoryProduct 查询中实际上“选择”了哪个类别。

将它映射到这样的实体,也许?

CategorySelected
----------------
Category Category { get; set; }
bool IsSelected { get; set;

我尝试使用 QueryOver 找到答案,但没有成功。这在“或多或少”的简单查询中是否可能?任何帮助深表感谢。谢谢!

米卡尔

4

1 回答 1

3

实现这一目标的一种方法是创建条件 SELECT 语句。在 SQL Server 的情况下,我们想生成这样的东西

SELECT CASE CategoryId IN (.... subselect ) THEN 1 ELSE 0 END ...

但是感谢 NHibernate 和抽象查询 API,我们可以创建查询以在所有支持的数据库方言中工作。

让我们尝试创建一个新解决方案的草案。我们先调整SubQuery一下

var subQuery = QueryOver.Of(() => cp)
    .Select(Projections.Distinct(Projections.Property(() => cp.CategoryId)));

现在我们将创建条件语句

var isSelected = Projections.Conditional(
    Subqueries.PropertyIn("Id", subQuery) // Category ID to be in the inner select
    , Projections.Constant(1)
    , Projections.Constant(0)
);

我们会将该条件注入到QueryOver并用于Transformers正确填充 Category 的属性(包括 virtual IsSelected

Category category = null
result = Session.QueryOver(() => cat)
    // SELECT clause is now built
    .SelectList(list => list
        .Select(isSelected).WithAlias(() => category.IsSelected)
        .Select(ca => ca.Id).WithAlias(() => category.Id)
        ... // all properites we would like to be populated
    )
    // Transform results into Category again
    .TransformUsing(Transformers.AliasToBean<Category>())
    .List<Category>();

现在,我们的新IsSelected属性(未映射,但仅用于此 SELECT (projections) )填充了正确的信息。

注意:这种方法是有效的,但声明应视为草稿。在您的情况下可能需要进行一些调整...

于 2013-09-15T14:58:59.383 回答