NHibernate QueryOver SQLFunction in where clause

天大地大妈咪最大 提交于 2019-12-23 17:53:04

问题


I would like to query a table having multiple rows, each with a timestamp with data coming at ten minute intervals. I would like to find the beginning of any missing data, which is where there is not a timestamp equaling the next ten minute interval, like this:

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]

I have this so far, but I fail to see how to build the query to let me do the b.[timestamp] = dateadd(mi, 10, a.[timestamp]) in the query above:

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

I can not get my head round the restriction on the sqlfuntion part - Nhibernate just won't let me do the comparison of the sqlfunction and my timestamp.

I hope I am on the right track with the code above, but please correct me if I'm totally off with my attempt at solving this...

Kind regards


回答1:


You are on the right track. You need to use Restrictions.EqProperty instead of Restrictions.Eq since you are comparing two projections and not a projection and a constant value.

Also, you can use an Expression to access the TimeStamp property of the inner query instead of using a string.

The following code works for me on Sql Server 2008, but it may require a bit of tweaking for other database engines:

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

Which should generate the following SQL (at least on 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)


来源:https://stackoverflow.com/questions/11097193/nhibernate-queryover-sqlfunction-in-where-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!