有沒有簡單的方法,使您LINQ查詢工作。你的情況的問題是,NHibernate不知道如何翻譯DateTime.AddHours(double hours)
方法。但是,您可以使用HQL來編寫類似的查詢嗎?顯然不是。沒有標準的HQL AddHours函數。因此你必須註冊這個新功能。 NHibernate使用方言在hql和供應商特定的SQL語法之間進行轉換。爲了做到這一點,你必須創建一個新的方言類從派生出來並覆蓋RegisterFunctions方法。 但是,這隻解決了問題的前半部分。接下來你必須展示NHibernate如何在LINQ中使用這個函數。您必須在DateTime.AddHours(double hours)
方法和先前註冊的自定義hql函數之間「映射」。 NHibernate使用註冊表來達到這個目的。您將不得不擴展默認的linq-to-hql註冊表。
我將表明,與NHibernate的工作爲例3.3
創建一個新的方言類(我的例子中使用預定義的MsSql2008Dialect)
public class EnhancedMsSql2008Dialect : MsSql2008Dialect
{
protected override void RegisterFunctions() {
base.RegisterFunctions();
RegisterFunction("add_hours", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(hour, ?1, ?2)"));
}
}
創建知道一個新的LINQ到HQL生成器類如何翻譯AddHours方法
using NHibernate.Linq.Functions;
using NHibernate.Linq;
using NHibernate.Hql.Ast;
public class DateTimeMethodsHqlGenerator : BaseHqlGeneratorForMethod
{
public DateTimeMethodsHqlGenerator() {
SupportedMethods = new[] {
ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1))
};
}
public override HqlTreeNode BuildHql(System.Reflection.MethodInfo method, System.Linq.Expressions.Expression targetObject, System.Collections.ObjectModel.ReadOnlyCollection arguments, HqlTreeBuilder treeBuilder, NHibernate.Linq.Visitors.IHqlExpressionVisitor visitor) {
return treeBuilder.MethodCall("add_hours", visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(targetObject).AsExpression());
}
}
擴展默認LINQ到HQL註冊表類
public class EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public EnhancedLinqToHqlGeneratorsRegistry() : base() {
//
RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator());
}
}
配置
cfg.DataBaseIntegration(c => {
c.Dialect<EnhancedMsSql2008Dialect>();
});
cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>();
是否使用NH3.3?並通過代碼映射? – Rippo
是的,我同時使用 –