当您使用NHibernate“获取”映射对象时,它会向数据库输出SELECT查询。它使用参数输出;所以,如果我根据租户ID和名称查询汽车列表,我会得到:
select Name, Location from Car where tenantID=@p0 and Name=@p1
这有很好的好处,我们的数据库基于此查询和结果创建(和缓存)查询计划,因此当它再次运行时,查询速度要快得多,因为它可以从缓存加载计划。 / p>
这个问题是我们是一个多租户数据库,几乎所有的索引都是分区对齐的。我们的租户拥有截然不同的数据集;一个租户可能有5辆汽车,而另一个可能有5万辆。因为NHibernate这样做,它具有我们的数据库创建和缓存运行它的第一个租户的计划的净效果。对于运行查询的后续租户而言,此计划可能效率不高。
我想要做的是强迫NHibernate不参数化某些参数;即租户ID。所以我想要查询:
select Name, Location from Car where tenantID=55 and Name=@p0
我无法弄清楚如何在HBM.XML映射中执行此操作。我如何指示NHibernate如何使用参数?或者我可以完全关闭参数吗?
答案 0 :(得分:0)
确定大家,我明白了。
我这样做是用我自己的自定义驱动程序覆盖 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 属性中注册此自定义驱动程序。
希望这有助于某人!