ServiceStack可以通过System.DateTime值执行查询吗?

我正在评估ServiceStack以确定它是否适用于通用REST服务器构建目的,并且我试图扩展Northwind演示,我已经在本地更新了它以使用ServiceStack 4.0.44。 我的调整代码在Bitbucket上,从git转移到hg,然后添加我自己的更改。

我的代码和上游serviceStack之间的区别。例子northwind demo是以下补充:

A ... / date / Route已添加到订单的ServiceModel.Operations对象中:

 namespace ServiceStack.Northwind.ServiceModel.Operations
 {
     ...

     [Route("/orders")]
     [Route("/orders/date/{ByDate}")] // ADDED!
     [Route("/orders/page/{Page}")]
     [Route("/customers/{CustomerId}/orders")]
    public class Orders
    {
        public int? Page { get; set; }
        public DateTime? ByDate { get; set; } // ADDED!
        public string CustomerId { get; set; }
    }

然后,这个案例的一个处理程序被添加到服务中,该服务在运行时爆炸了一个奇怪的LINQ故障: variable 'o' of type 'ServiceStack.Northwind.ServiceModel.Types.Order' referenced from scope '', but it is not defined...

Source = System.Core



namespace ServiceStack.Northwind.ServiceInterface
{
    public class OrdersService : Service
    {
        private const int PageCount = 20;


        public object Get(Orders request)
        {
            List<Order> orders = null;
            if (request.ByDate.HasValue)
            { // date provided

                // broken LINQ #1 -- EXCEPTION HERE AT RUNTIME!
                orders = Db.Select<Order>(order => order.Where<Order>(o => o.OrderDate.Value.Date == request.ByDate.Value.Date ));

                /*
                 broken LINQ #2
                orders =
                    Db.Select( 
                        Db.From<Order>().
                        Where(o => (o != null) && o.OrderDate.HasValue && (request.ByDate.Value.Date == o.OrderDate.Value.Date)
                             )
                        ); 
                        */


            }
            else if (request.CustomerId.IsNullOrEmpty())
            {
                orders = Db.Select<Order>(order => order.OrderByDescending(o => o.OrderDate))
                      .Skip((request.Page.GetValueOrDefault(1) - 1) * PageCount)
                      .Take(PageCount)
                      .ToList();
            }
            else
            {
                orders = Db.Select<Order>(order => order.Where(o => o.CustomerId == request.CustomerId));
            }

            if (orders.Count == 0)

这个异常表明我不知道如何编写一个LINQ表达式来查询日期,或者它可能表明SQLite的ORM中存在内部错误,或者整体框架中存在错误,或者我做错了什么。

当我尝试通过DateTime值查询时,类似的运行时崩溃也为Firebird提供程序重现,所以它可能是SQLite和Firebird ORMLite提供程序中的一个错误。

  System.InvalidOperationException was unhandled by user code
  HResult = -2146233079
  Message = variable 'o' of type 'ServiceStack.Northwind.ServiceModel.Types.Order' referenced from scope '', but it is not defined
    Source = System.Core
  StackTrace:
                at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
       at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
       at System.Linq.Expressions.ParameterExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
       at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
       at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.Compiler.VariableBinder.VisitUnary(UnaryExpression node)
       at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
       at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
       at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
       at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
       at System.Linq.Expressions.Compiler.VariableBinder.Bind(LambdaExpression lambda)
       at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator)
       at ServiceStack.OrmLite.SqlExpression`1.VisitMemberAccess(MemberExpression m)
       at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
       at ServiceStack.OrmLite.SqlExpression`1.VisitBinary(BinaryExpression b)
       at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
       at ServiceStack.OrmLite.SqlExpression`1.VisitBinary(BinaryExpression b)
       at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
       at ServiceStack.OrmLite.SqlExpression`1.VisitLambda(LambdaExpression lambda)
       at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
       at ServiceStack.OrmLite.SqlExpression`1.AppendToWhere(String condition, Expression predicate)
       at ServiceStack.OrmLite.SqlExpression`1.Where(Expression`1 predicate)
       at ServiceStack.Northwind.ServiceInterface.OrdersService.Get(Orders request) in C:devServiceStack.ExamplessrcServiceStack.NorthwindServiceStack.Northwind.ServiceInterfaceOrdersService.cs:line 19
       at lambda_method(Closure, Object, Object)
       at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)
  InnerException:

解决方法:

如果我自己写一个SQL where子句声明,它可以工作:

  if (request.ByDate.HasValue)
            { // date provided
                string condition = string.Format("OrderDate = '{0}'", request.ByDate.Value.Date.ToString("yyyy-MM-dd") );
                orders = Db.Select<Order>(condition);

ServiceStack肯定可以通过DateTime进行查询。 但在你的情况下,你只是试图按日期部分查询,忽略时间(类似date(OrderDate)= date(ByDate))。 事情是 - 您使用的表达式(o.OrderDate.Value.Date == request.ByDate.Value.Date)可能看起来很简单,但实际上它有时用复杂的表达式树来表示。 该表达式树由ORM探索并转换为原始的sql查询。 现在,表达式可以是任意复杂的,当然,并不是所有的表达式都可以转换为SQL查询。 ORM的开发人员应该明确地考虑哪些表达式可能对实现有用。 在这种情况下,最有可能的情况是,当您访问DateTime实例的.Date属性时,ORM的开发人员可能无法处理该案例,或者出于某种原因,甚至无法处理此类案例。 你期望这将被转换成类似date(OrderDate)sql的东西,但事实并非如此。 其他ORM(实体框架为例)具有特殊的功能,可以在表达式中调用(如下所示:o => DbFunctions.Date(o.OrderDate)),但ServiceStack不具备仅用于日期比较的功能,我知道。

长话短说 - 我会说这不是一个错误,但只是不支持的功能。 当然,他们可能会处理这个问题并抛出更好的例外,但事实就是如此。

最后,只需通过DateTime查询,就像您的问题所述,只需执行以下操作:

var byDate = request.ByDate.Value.Date;                
orders = Db.Select<Order>(order => order.OrderDate == byDate);
链接地址: http://www.djcxy.com/p/65971.html

上一篇: Can ServiceStack do a query by System.DateTime value?

下一篇: ServiceStack AutoQuery not working for DateTime values