outlookrperson
outlookrperson

Reputation: 2821

Dealing with DateTime using "Linq Methods"

[ASP.NET 4.0 / EF 4.1]

Hi,

I´m trying to use "Linq Methods" to filter a datasource based on datetime fields, but I´m getting the error: "Only primitive types ('such as Int32, String, and Guid') are supported in this context".

I know that Entity Framework have some limitations when dealing with dates, but what I need is some elegant solution to deal with this issue.

My code is:

    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();
    }

When the code executes the query (result.ToList()) it throws the exception. If I remove the datetime .Where clauses, it works fine.

Thanks!

Solution

I have changed my code to:

    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();
    }

If someone has a better solution, please let me know.

Upvotes: 3

Views: 2471

Answers (1)

Bart
Bart

Reputation: 10015

You're using a nullable type DateTime? in your example. I'm not sure if your database column allows NULL, but I'd use date.Value to pass the value of the parameter to be sure EF doesn't fall over it. Note that with nullable types, you can als use the HasValue property to check if your parameter contains a proper value. This results in:

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

Upvotes: 4

Related Questions