2013-08-21 29 views
0

如何表达NHibernate的QueryOver语法查询加入NHibernate的子查询(加入多个列)

Select * from 
     (select name, Max(date) as date from items group by name) as latest 
    inner join items as i 
     on i.name=latest.name and i.date = latest.date 

因此,我期望从items表中获得每个名称的最大日期记录。

表中的每一项对应ItemEnity类:

[Class(Table = "items")] 
public class ItemEnity 
{ 
    [Id(Name = "Id")] 
    [Generator(1, Class = "native")] 
    public virtual long Id { get; set; } 

    [Property(NotNull = true)] 
    public virtual string Name { get; set; } 

    [Property(NotNull = true)] 
    public virtual DateTime Date { get; set; } 

    // other columns ... 
} 

我已经成功在一个强类型的形式来表达子查询:

public class ItemLatest 
{ 
    public string Name { get; set; } 
    public DateTime Date { get; set; } 
} 

// ... 

ItemLatest latest = null; 

var subquery = QueryOver.Of<ItemEntity>().SelectList(list => list 
    .SelectGroup(i => i.Name).WithAlias(() => latest.Name) 
    .SelectMax(i => i.Date).WithAlias(() => latest.Date)) 
    .TransformUsing(Transformers.AliasToBean<ItemLatest>()); 

var result = subquery.GetExecutableQueryOver(session).List<ItemLatest>(); 

但我不知道怎么写加盟因为我找不到如何使用JoinQueryOver()来表示两个实体(在我的情况下为ItemLatest和ItemEnity)之间没有关系属性从一个到另一个的引用之间的连接。

+0

难道你不能在Linq语法中使用'Query ()'来编写它吗?它位于'NHibernate.Linq'命名空间 –

+0

不知道要作为Join()方法的“内部”IEnumerable参数传递什么。换句话说,我只有一个由查询生成的IQueryable () – Lu55

回答

1

JOIN在映射定义的ORM世界(包括NHibernate)中。所以,如果你想使用标准和JOIN,它必须在Referenced属性上。

例如,我们可以做的是创建一个新对象,例如ItemEnityMaxDate并将其映射到与您的SELECT MAX .. GROUP BY类似的视图。我们可以这样进行扩展,例如:

SELECT main.Id, main.Name, main.Date 
    FROM items main 
    INNER JOIN 
    (
     SELECT i.Name, Max(i.Date) AS Date FROM items i GROUP BY i.Name 
    ) AS latest 
    ON main.Name = latest.Name AND main.Date = latest.Date 

的C#ItemEnityMaxDate将作为ItemEntity相似(当然,我们将只需要标识),映射到上述的观点。 然后我们可以使用它作为子查询

// inner select 
var subquery = DetachedCriteria.For<ItemEnityMaxDate>() 
    .SetProjection(Projections.Property("Id")); 

// the ItemEntity 
var query = session.CreateCriteria<ItemEntity>() 
    .Add(Subqueries.PropertyIn("Id", subquery)); 
var list = query.List<ItemEntity>(); 

这可能不是唯一的方法。但通过这种方式,将您的“特殊查询”表示为对象...将可以工作

+0

您是否建议在DB中创建视图,然后将结果提取到C#对象?因为如果我能够在NHibernate上编写这样的查询,我肯定能够提取整个ItemEntity对象(通过在生成的SELECT子句中添加更多列) – Lu55

+0

不完全确定我是否理解您的评论。但是,是的,我可以在数据库和新的C#对象中创建新的视图。 NHibernate中的mapp都是只读的。使用新的ItemEntityMaxDate过滤ItemEntity。 –