c# - system_versioning - NHibernate HQL Generator per supportare tabelle temporali di SQL Server 2016



t sql for system_time (1)

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;

Sto cercando di implementare il supporto di base per le tabelle temporali di SQL Server 2016 in NHibernate 4.x. L'idea è di alterare l'istruzione SQL da

SELECT * FROM Table t0

a

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

Puoi trovare ulteriori informazioni sulle tabelle temporali in SQL Server 2016 here

Purtroppo, non ho trovato alcun modo per inserire FOR FOR SYSTEM_TIME AS OF '...' tra il nome della tabella e il suo alias. Non sono sicuro che i dialetti personalizzati lo supportino. L'unica soluzione funzionante che ho per ora è di aggiungere FOR SYSTEM_TIME statement all'interno di extra WHERE e il mio output SQL appare così

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

Per fare ciò, ho implementato il generatore e il dialetto come segue:

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"));
    }
}

Qualcuno può fornire un approccio migliore o campioni che potrei usare per andare avanti e inserire FOR SYSTEM_TIME AS OF istruzione tra il nome della tabella e il suo alias? In questo momento l'unica soluzione che posso vedere è di modificare SQL in OnPrepareStatement in SessionInterceptor ma credo che ci sia un approccio migliore ...





temporal-tables