繁体   English   中英

NHibernate HQL Generator支持SQL Server 2016时态表

[英]NHibernate HQL Generator to support SQL Server 2016 temporal tables

我试图在NHibernate 4.x中实现对SQL Server 2016时态表的基本支持。 想法是改变SQL语句

SELECT * FROM Table t0

SELECT * FROM Table FOR SYSTEM_TIME AS OF '2018-01-16 00:00:00' t0

您可以在此处找到有关SQL Server 2016中时态表的更多信息

不幸的是,我没有找到任何方法在表名和它的别名之间插入FOR FOR SYSTEM_TIME AS OF '...'语句。 我不确定自定义方言是否支持此功能。 我现在唯一可行的解​​决方案是在额外的WHERE附加FOR SYSTEM_TIME语句,我的输出SQL看起来像这样

SELECT * FROM Table t0 WHERE FOR SYSTEM_TIME AS OF '2018-01-16 00:00:00'=1

为此,我实现了生成器和方言,如下所示:

public static class AuditableExtensions
{
    public static bool AsOf(this IAuditable entity, DateTime date)
    {
        return true;
    }

    public static IQueryable<T> Query<T>(this ISession session, DateTime asOf) where T : IAuditable
    {
        return session.Query<T>().Where(x => x.AsOf(asOf));
    }
}

public class ForSystemTimeGenerator : BaseHqlGeneratorForMethod
{
    public static readonly string ForSystemTimeAsOfString = "FOR SYSTEM_TIME AS OF";

    public ForSystemTimeGenerator()
    {
        SupportedMethods = new[]
        {
            ReflectionHelper.GetMethod(() => AuditableExtensions.AsOf(null, DateTime.MinValue))
        };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, 
        ReadOnlyCollection<Expression> arguments,
        HqlTreeBuilder treeBuilder, 
        IHqlExpressionVisitor visitor)
    {
        return treeBuilder.BooleanMethodCall(nameof(AuditableExtensions.AsOf), new[]
        {
            visitor.Visit(arguments[1]).AsExpression()
        });
    }
}

public class MsSql2016Dialect : MsSql2012Dialect
{
    public MsSql2016Dialect()
    {
        RegisterFunction(nameof(AuditableExtensions.AsOf), new SQLFunctionTemplate(
            NHibernateUtil.Boolean, 
            $"{ForSystemTimeGenerator.ForSystemTimeAsOfString} ?1?2=1"));
    }
}

任何人都可以提供任何更好的方法或样本我可以用来向前移动并在表名和它的别名之间插入FOR SYSTEM_TIME AS OF语句吗? 此时我能看到的唯一解决方案是改变SessionInterceptor中的OnPrepareStatement中的SQL,但我相信还有一些更好的方法......

创建一个UDF(以所需的时间作为参数)并调用它而不是直接使用该表。

DECLARE @String1 NVARCHAR(100),
    @String2 NVARCHAR(100) ,
    @DateTime DATETIME= '2018-01-16 00:00:00';

 SET @String1 = 'SELECT * FROM Table2';
 SET @String2 = @String1 + ' FOR SYSTEM_TIME AS OF '''
 + CONVERT(VARCHAR(20), @DateTime, 120) + '''';
 SELECT  @String2;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM