控制有关参数的 NHIbernate 搜索查询输出

Controlling NHIbernate search query output regarding parameters

当您使用 NHibernate "fetch" 映射对象时,它会向数据库输出一个 SELECT 查询。它使用参数输出;因此,如果我根据租户 ID 和姓名查询汽车列表,我会得到:

select Name, Location from Car where tenantID=@p0 and Name=@p1

这对我们的数据库基于此查询和结果创建(和缓存)查询计划有很大好处,所以当它再次 运行 时,查询速度更快,因为它可以加载从缓存中计划。

问题是我们是一个多租户数据库,我们几乎所有的索引都是分区对齐的。我们的租户拥有截然不同的数据集;一个租户可以拥有 5 辆汽车,而另一个租户可以拥有 50,000 辆。因此,由于 NHibernate 这样做,它具有我们的数据库为 运行 的第一个租户创建和缓存计划的净效果。对于 运行 查询的后续租户,此计划可能效率不高。

我想做的是强制 NHibernate 不要参数化某些参数;即租户ID。所以我希望查询读取:

select Name, Location from Car where tenantID=55 and Name=@p0

我不知道如何在 HBM.XML 映射中执行此操作。我如何指示 NHibernate 如何使用参数?或者我可以完全关闭参数吗?

好的大家,我明白了。

我的做法是用我自己的自定义驱动程序覆盖 SqlClientDriver,如下所示:

 public class CustomSqlClientDriver : SqlClientDriver
{
    private static Regex _partitionKeyReplacer = new Regex(@".PartitionKey=(@p0)", RegexOptions.Compiled);
    public override void AdjustCommand(IDbCommand command)
    {
        var m = _tenantIDReplacer.Match(command.CommandText);

        if (!m.Success)
            return;

        //  replace the first parameter with the actual partition key
        var parameterName = m.Groups[1].Value;

        // find the parameter value
        var tenantID = (IDbDataParameter ) command.Parameters[parameterName];
        var valueOfTenantID = tenantID.Value;

        // now replace the string
        command.CommandText = _tenantIDReplacer.Replace(command.CommandText, ".TenantID=" + valueOfTenantID);
    }
} }

我覆盖了 AdjustCommand 方法并使用 Regex 替换了 tenantID。这行得通;不确定是否有更好的方法,但我真的不想打开 NHibernate 并开始弄乱核心代码。

您必须在 SessionFactoryconnection.driver_class 属性 中注册此自定义驱动程序初始化。

希望对大家有所帮助!