控制有关参数的 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 并开始弄乱核心代码。
您必须在 SessionFactory 的 connection.driver_class 属性 中注册此自定义驱动程序初始化。
希望对大家有所帮助!
当您使用 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 并开始弄乱核心代码。
您必须在 SessionFactory 的 connection.driver_class 属性 中注册此自定义驱动程序初始化。
希望对大家有所帮助!