gpt4 book ai didi

c# - NHibernate HQL Generator 支持 SQL Server 2016 时态表

转载 作者:IT王子 更新时间:2023-10-29 04:19:46 25 4
gpt4 key购买 nike

我正在尝试在 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 语句吗?目前我能看到的唯一解决方案是在 SessionInterceptor 中更改 OnPrepareStatement 中的 SQL,但我相信有一些更好的方法...

最佳答案

NHibernate Reference 5.1 中有关于使用 NHibernate 临时表的信息,地址为 NHibernate Reference

19.1 节中的示例展示了如何使用临时表:

首先定义一个过滤器:

<filter-def name="effectiveDate">
<filter-param name="asOfDate" type="date"/>
</filter-def>

然后将其附加到一个类中:

<class name="Employee" table="Employee For System_Time All" ...>
...
<many-to-one name="Department" column="dept_id" class="Department"/>
<property name="EffectiveStartDate" type="date" column="eff_start_dt"/>
<property name="EffectiveEndDate" type="date" column="eff_end_dt"/>
...
<!--
Note that this assumes non-terminal records have an eff_end_dt set to
a max db date for simplicity-sake
-->
<filter name="effectiveDate"
condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
</class>

然后您需要在 session 上启用过滤器:

   ISession session = ...;
session.EnableFilter("effectiveDate").SetParameter("asOfDate", DateTime.Today);
var results = session.CreateQuery("from Employee as e where e.Salary > :targetSalary")
.SetInt64("targetSalary", 1000000L)
.List<Employee>();

希望这能让人们开始。

关于c# - NHibernate HQL Generator 支持 SQL Server 2016 时态表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48280776/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com