NHibernate HQL Generator支持SQL Server 2016时态表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NHibernate HQL Generator支持SQL Server 2016时态表相关的知识,希望对你有一定的参考价值。
我试图在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 here中找到有关时态表的更多信息
不幸的是,我没有找到任何方法在表名和别名之间插入FOR FOR SYSTEM_TIME AS OF '...'
语句。我不确定自定义方言是否支持此功能。我现在唯一可行的解决方案是在额外的FOR SYSTEM_TIME
中附加WHERE
语句,我的输出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
语句吗?在这一刻,我能看到的唯一解决方案是改变OnPrepareStatement
中的SessionInterceptor
中的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;
以上是关于NHibernate HQL Generator支持SQL Server 2016时态表的主要内容,如果未能解决你的问题,请参考以下文章
Nhibernate HQL 匿名类(严格说是map的使用以及构造函数的使用
NHibernate HQL 生成器支持 SQL Server 2016 时态表
如何在 Hql 中执行 ThenFetch 以及如何分解 nhibernate linq 中的许多连接?