Không có cách nào dễ dàng để làm cho LINQ của bạn truy vấn. Vấn đề với kịch bản của bạn là NHibernate không biết làm thế nào để dịch DateTime.AddHours(double hours)
phương pháp. Nhưng bạn có thể sử dụng HQL để viết một truy vấn tương tự? Rõ ràng là không. Không có chức năng HQL AddHours chuẩn nào. Do đó bạn phải đăng ký chức năng mới này. NHibernate sử dụng các phương ngữ để dịch giữa cú pháp SQL của nhà cung cấp và SQL cụ thể. Để thực hiện điều này, bạn phải tạo một lớp phương ngữ mới xuất phát từ một phương thức xuất hiện và ghi đè lên phương thức RegisterFunctions. Nhưng điều này chỉ giải quyết được nửa đầu của vấn đề. Tiếp theo bạn phải hiển thị NHibernate làm thế nào để sử dụng chức năng này trong LINQ. Bạn phải "ánh xạ" giữa phương thức DateTime.AddHours(double hours)
và hàm hql tùy chỉnh được đăng ký ưu tiên. NHibernate sử dụng một đăng ký cho mục đích này. Bạn sẽ phải mở rộng sổ đăng ký linq-to-hql mặc định.
tôi sẽ giới thiệu một ví dụ mà làm việc với NHibernate 3,3
Tạo một lớp phương ngữ mới (ví dụ của tôi sử dụng MsSql2008Dialect được xác định trước)
public class EnhancedMsSql2008Dialect : MsSql2008Dialect
{
protected override void RegisterFunctions() {
base.RegisterFunctions();
RegisterFunction("add_hours", new SQLFunctionTemplate(NHibernateUtil.DateTime, "dateadd(hour, ?1, ?2)"));
}
}
Tạo một lớp phát LINQ-to-HQL mới biết làm thế nào để dịch AddHours phương pháp
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());
}
}
Mở rộng mặc định LINQ-to-HQL lớp registry
public class EnhancedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public EnhancedLinqToHqlGeneratorsRegistry() : base() {
//
RegisterGenerator(ReflectionHelper.GetMethodDefinition((DateTime x) => x.AddHours(1)), new DateTimeMethodsHqlGenerator());
}
}
Configure
cfg.DataBaseIntegration(c => {
c.Dialect<EnhancedMsSql2008Dialect>();
});
cfg.LinqToHqlGeneratorsRegistry<EnhancedLinqToHqlGeneratorsRegistry>();
Bạn có sử dụng NH3.3? và lập bản đồ theo mã? – Rippo
Có, tôi sử dụng cả hai –