【发布时间】:2018-06-25 03:12:45
【问题描述】:
我正在尝试在 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 '...' 语句的任何方法。我不确定自定义方言是否支持这一点。我现在唯一可行的解决方案是在额外的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 语句?目前我能看到的唯一解决方案是在OnPrepareStatement 中更改SessionInterceptor 中的SQL,但我相信有更好的方法...
【问题讨论】:
标签: c# sql-server nhibernate sql-server-2016 temporal-tables