NHibernate 中日期时间的 LIKE 查询

Posted

技术标签:

【中文标题】NHibernate 中日期时间的 LIKE 查询【英文标题】:LIKE query for DateTime in NHibernate 【发布时间】:2010-04-14 17:07:27 【问题描述】:

对于 varchar 类型的列,我可以编写这样的搜索查询:

public IList<Order> GetByName(string orderName)

 using (ISession session = NHibernateHelper.OpenSession())
 
  return session.CreateCriteria<Order>().
   Add(Restrictions.Like("Name", string.Format("%0%", orderName))).
   List<Order>();
 

如何为具有 DateTime 类型的列实现类似的搜索查询?

public IList<Order> GetByDateTime(string str)

    using (ISession session = NHibernateHelper.OpenSession())
    
        return session.CreateCriteria<Order>()
            .Add(Restrictions.Like(Projections.Cast(NHibernateUtil.String, Projections.Property("Created")),
                                    '%' + str + '%'))
            .List<Order>();
    

也就是说,如果该方法传递了日期和部分时间(例如“25.03.2010 19”),则显示所有订单都在这段时间内进行: 25.03.2010 19:22:00 25.03.2010 19:44:00 25.03.2010 19:59:00

【问题讨论】:

NHibernate 不能做任何用 sql 做不了的事情,所以你需要像 Aaronaught 建议的那样在 C# 中创建自己的日期解析函数 【参考方案1】:

只需检查日期是否在您想要的范围内:

DateTime beginDate = new DateTime(2010, 3, 25, 19, 0, 0);
DateTime endDate = new DateTime(2010, 3, 25, 20, 0, 0);
return session.CreateCriteria<Order>()
   .Add(Expression.Between("OrderDate", beginDate, endDate))
   .List<Order>();

【讨论】:

您的回答是可以理解和合乎逻辑的。但是......用户只指定日期字符串,如“14.04.2010”、“2010”、“14.04”、“04.2010 22:06”等。 @Anry: 如果201014.04 都是有效输入,你是如何消除歧义的? 14.04 可能表示 4 月 14 日,也可能表示 2014 年 4 月。也可能表示下午 2:04。如果输入只是10,应该将其解释为 2010 年还是 10 月?最简单的解决方案是询问用户日期范围而不是任意文本输入。对用户更友好但难度呈指数增长的解决方案是使用日期算术和可能的一些正则表达式将模糊日期解析为可用范围。【参考方案2】:

我在使用 LINQ 时遇到了类似的问题,并在 vikram nayak 就此处提出的问题发布的答案的帮助下修复了它:Nhibernate LINQ DateTime.AddDay does not work。

这就是我的做法: 我在 vikram 的示例中替换了以下类:

public class ExtendedLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry

    public ExtendedLinqtoHqlGeneratorsRegistry()
    
        this.Merge(new DateTimeToShortDateStringGenerator());
        //I had to use the lines below instead.
        //MethodInfo method = ReflectionHelper.GetMethodDefinition<DateTime>(x => x.ToShortDateString());
        //RegisterGenerator(method, new DateTimeToShortDateStringGenerator());
    


public class DateTimeToShortDateStringGenerator : BaseHqlGeneratorForMethod

    public DateTimeToShortDateStringGenerator()
    
        SupportedMethods = new[]
        
            ReflectionHelper.GetMethodDefinition<DateTime>(x => x.ToShortDateString())
        ;
    

    public override HqlTreeNode BuildHql(MethodInfo method, System.Linq.Expressions.Expression targetObject, ReadOnlyCollection<System.Linq.Expressions.Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    
        return treeBuilder.MethodCall("DateTimeToShortDateString", visitor.Visit(targetObject).AsExpression());
    


public class CustomDialect : MsSql2008Dialect

    public CustomDialect()
    
        RegisterFunction(
            "DateTimeToShortDateString",
            new SQLFunctionTemplate(
            NHibernateUtil.DateTime,
            "CONVERT(NVARCHAR(10), ?1, 105)"
            )
        );
    

然后您可以使用以下语法:

using (session.BeginTransaction())

    var patients = session.Query().Where(p => p.BirthDate.ToShortDateString().Contains("1975"));

【讨论】:

以上是关于NHibernate 中日期时间的 LIKE 查询的主要内容,如果未能解决你的问题,请参考以下文章

like 查询怎样查询范围

如何使用 NHibernate QueryOver 重新创建这个复杂的 SQL 查询?

sqlserver ,用like ‘日期' 查询

LIKE 运算符无法正常使用日期

MySQL 使用 LIKE 和 WHERE 选择

SqlServer数据库中,日期的模糊查询