Я пытаюсь реализовать базовую поддержку временных таблиц SQL Server 2016 в NHibernate 4.x. Идея состоит в том, чтобы изменить оператор SQL с
SELECT * FROM Table t0
to
SELECT * FROM Table FOR SYSTEM_TIME AS OF '2018-01-16 00:00:00' t0
Дополнительную информацию о темпоральных таблицах можно найти в SQL Server 2016 здесь
К сожалению, я не нашел способа вставить выражение 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
между именем таблицы и ее псевдонимом? На данный момент единственное решение, которое я вижу, - это изменить SQL в OnPrepareStatement
на SessionInterceptor
, но я считаю, что есть лучший подход ...
FOR SYSTEM_TIME AS OF
является подсказкой для таблицы, а не логическим предикатом для предложенияWhere
. - person Panagiotis Kanavos   schedule 16.01.2018FOR SYSTEM_TIME AS OF
часть перед псевдонимом таблицы, но это возможно только изOnPrepareStatement
. Было бы здорово сгенерировать действительный SQL в HqlGenerator, но я не уверен, возможно ли это - person veeroo   schedule 09.11.2018