【问题标题】:LIKE query for DateTime in NHibernateNHibernate 中日期时间的 LIKE 查询
【发布时间】: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# 中创建自己的日期解析函数

标签: nhibernate orm criteria sql-like


【解决方案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"));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    相关资源
    最近更新 更多