NHibernate QueryOver在where子句中的SQLFunction

时间:2012-06-19 08:27:22

标签: nhibernate subquery queryover

我想查询一个包含多行的表,每行有timestamp,数据间隔为十分钟。我想找到任何缺失数据的开头,这是没有timestamp等于下一个十分钟间隔的地方,如下所示:

select a.[timestamp]
from [table] as a
where not exists (select 1
                  from [table] as b
                  where a.[id] = b.[id] 

                    and b.[timestamp] = dateadd(mi, 10, a.[timestamp]))

order by a.[timestamp]

到目前为止我有这个,但是我没有看到如何构建查询以让我执行 b。[timestamp] = dateadd(mi,10,a。[timestamp])上面的查询:

Table tableAlias = null;

IList<DateTimeOffset> dateTimeOffsets = session.QueryOver(() => tableAlias)
.WithSubquery
.WhereNotExists(QueryOver.Of<Table>()
.Where(x => x.Id == tableAlias.Id)

.And(Restrictions.Eq(Projections.SqlFunction("addminutes",
                                             NHibernateUtil.DateTimeOffset,
                                             new[]
                                             {
                                               Projections.Property("Timestamp"),
                                               Projections.Constant(10)
                                             }),
                                             <insert timestamp property again here>))

.Select(Projections.Constant(1)))
.Select(x => x.Timestamp)
.List<DateTimeOffset>();

我无法理解sqlfuntion部分的限制 - Nhibernate我不会让我对sqlfunction和我的时间戳进行比较。

我希望我能够使用上面的代码走上正轨,但如果我完全没有尝试解决这个问题,请纠正我......

亲切的问候

1 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。您需要使用Restrictions.EqProperty而不是Restrictions.Eq,因为您要比较两个投影,而不是投影和常量值。

此外,您可以使用Expression访问内部查询的TimeStamp属性,而不是使用字符串。

以下代码适用于Sql Server 2008,但可能需要对其他数据库引擎进行一些调整:

Table a = null;

session.QueryOver<Table>(() => a)
    .WithSubquery
    .WhereNotExists(
        QueryOver.Of<Table>()
            .Where(t => t.Id == a.Id)
            .And(Restrictions.EqProperty(
                Projections.SqlFunction(
                    "addminutes",
                    NHibernateUtil.DateTimeOffset,
                    Projections.Constant(10),
                    Projections.Property(() => a.TimeStamp)),
                Projections.Property(() => a.TimeStamp)))
            .Select(Projections.Constant(1)))
.Select(t => t.TimeStamp)
.List<DateTimeOffset>();

哪个应生成以下SQL(至少在Sql Server 2008上):

SELECT this_.TimeStamp as y0_
FROM   [Table] this_
WHERE  not exists (SELECT 1 /* @p0 */ as y0_
                   FROM   [Table] this_0_
                   WHERE  this_0_.Id = this_.Id
                          and dateadd(minute, 10 /* @p1 */, this_.TimeStamp) = this_.TimeStamp)