使用“Linq方法”处理DateTime

3

[ASP.NET 4.0 / EF 4.1]

你好,

我想使用“Linq方法”根据日期字段过滤数据源,但是我遇到了错误:“仅支持原始类型(例如Int32、String和Guid)在此上下文中”。我知道Entity Framework处理日期时有一些限制,但我需要一种优雅的解决方案来处理这个问题。

我的代码如下:

    public IList<Order> GetOrders(int? orderId = null, string customerId = null, int? employeeId = null, DateTime? orderDateFrom = null, DateTime? orderDateUntil=null, DateTime? requiredDate = null, DateTime? shippedDate = null)
    {
        IQueryable<Order> result;

        result = from order in ctx.Orders.Include("Order_Details")
                 select order;

        // Apply filters to the base query
        if (orderId != null)
            result = result.Where(o => o.OrderID.Equals(orderId));

        if (!String.IsNullOrEmpty(customerId))
            result = result.Where(o => o.CustomerID.ToUpper().Equals(customerId.ToUpper()));

        if (employeeId != null)
            result = result.Where(o => o.EmployeeID.Equals(employeeId));

        if (orderDateFrom != null)
            result = result.Where(o => o.OrderDate >= orderDateFrom);

        if (orderDateUntil != null)
            result = result.Where(o => o.OrderDate <= orderDateUntil);

        if (requiredDate != null)
            result = result.Where(o => o.RequiredDate == requiredDate);

        if (shippedDate != null)
            result = result.Where(o => o.ShippedDate == shippedDate);

        return result.ToList();
    }

当代码执行查询(result.ToList())时,会抛出异常。如果我删除 datetime .Where 子句,它就可以正常工作。

谢谢!

解决方案

我已经将我的代码更改为:

    public IList<Order> GetOrders(int? orderId = null, string customerId = null, int? employeeId = null, DateTime? orderDateFrom = null, DateTime? orderDateUntil=null, DateTime? requiredDate = null, DateTime? shippedDate = null)
    {
        IQueryable<Order> result;

        result = from order in ctx.Orders.Include("Order_Details")
                 select order;

        // Apply filters to the base query
        if (orderId != null)
            result = result.Where(o => o.OrderID.Equals(orderId.Value));

        if (!String.IsNullOrEmpty(customerId))
            result = result.Where(o => o.CustomerID.ToUpper() == customerId.ToUpper());

        if (employeeId != null)
            result = result.Where(o => o.EmployeeID == employeeId.Value);

        if (orderDateFrom != null)
            result = result.Where(o => o.OrderDate >= orderDateFrom.Value);

        if (orderDateUntil != null)
            result = result.Where(o => o.OrderDate <= orderDateUntil.Value);

        if (requiredDate != null)
            result = result.Where(o => o.RequiredDate == requiredDate.Value);

        if (shippedDate != null)
            result = result.Where(o => o.ShippedDate == shippedDate.Value);

        return result.ToList();
    }

如果有更好的解决方案,请告诉我。

哦,一定是4.1版本的问题,因为4.0支持这种日期格式;我们有类似于你们的日期检查,它可以正常工作。你在使用Code First吗? - Brian Mains
我记不清了,DateTime.Compare(t1, t2) 在 EF linq 查询中能用吗? - FlyingStreudel
在上面的代码中比较DateTime在EF 4.1中也可以工作。这很奇怪。你使用SQL Server吗?还是SQL Server CE版本?或者其他数据库? - Slauma
1个回答

4

您的示例中使用了可空类型 DateTime?。我不确定您的数据库列是否允许为空,但我建议使用 date.Value 来传递参数值以确保 EF 不会出现错误。请注意,在可空类型中,您还可以使用 HasValue 属性来检查参数是否包含正确的值。这样做可以得到以下结果:

if (orderDateFrom.HasValue)
   result = result.Where(o => o.OrderDate >= orderDateFrom.Value);

这看起来更加简洁,没错。但是与可空类型的比较实际上也可以工作,即使在LINQ to Entities中也是如此。我刚刚测试了所有4种组合(OrderDateorderDateFrom是否为空),在我的示例中它总是有效的,我从未不得不使用.Value - Slauma
感谢@Bart。这真的是我的错,因为我不能使用诸如result = result.Where(o => o.OrderID.Equals(orderId))的表达式。我必须使用表达式result = result.Where(o => Equals(orderId.Value))。 因此,就我所了解的而言,这个问题不仅涉及DateTime(请参阅OrderID),而且涉及与引用类型的比较。 - outlookrperson
@Slauma,你能提供一些代码片段来证明你的说法吗?谢谢。 - outlookrperson
@rperson:我现在明白了。当我使用可空类型的Equals时,我也确实遇到了你所描述的异常。你确定这不是你唯一的问题吗?如果你从 DateTime 过滤器中删除.Value,你真的还会得到异常吗?(我的示例与你的 DateTime Where 子句非常相似,只是使用了其他类和属性名称。) - Slauma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接