LINQ to SQL - 为什么不能在ORDER BY之后使用WHERE?

MCS*_*MCS 9 c# linq linq-to-sql

以下代码:

// select all orders
var orders = from o in FoodOrders
             where o.STATUS = 1
             order by o.ORDER_DATE descending
             select o;

// if customer id is specified, only select orders from specific customer
if (customerID!=null)
{
    orders = orders.Where(o => customerID.Equals(o.CUSTOMER_ID));
}
Run Code Online (Sandbox Code Playgroud)

给我以下错误:

无法将类型'System.Linq.IQueryable'隐式转换为'System.Linq.IOrderedQueryable'.存在显式转换(您是否错过了演员?)

我通过在最后进行排序来修复错误:

// select all orders
var orders = from o in FoodOrders
             where o.STATUS = 1
             select o;

// if customer id is specified, only select orders from specific customer
if (customerID!=null)
{
    orders = orders.Where(o => customerID.Equals(o.CUSTOMER_ID));
}

// I'm forced to do the ordering here
orders = orders.OrderBy(o => o.ORDER_DATE).Reverse();
Run Code Online (Sandbox Code Playgroud)

但我想知道为什么会出现这种限制?API的设计原因是where在使用order by运算符后无法添加约束的原因是什么?

Jon*_*eet 13

返回类型OrderByIOrderedQueryable<T>,所以这是orders变量的类型(部分原因是你在末尾有一个无操作投影) - 但返回类型Where只是IQueryable<T>.基本上你已经有了一个无操作投影的混合物一个隐式类型的局部变量查询的最后一个活动部分是订货,并且你想要再重新分配变量.基本上,这是一个不愉快的组合.

你可以像这样解决它:

IQuerable<FoodOrders> orders = from o in FoodOrders
                               where o.STATUS == 1
                               order by o.ORDER_DATE descending
                               select o;

// if customer id is specified, only select orders from specific customer
if (customerID!=null)
{
    orders = orders.Where(o => customerID.Equals(o.CUSTOMER_ID));
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用点表示法明确地执行了无操作投影(我怀疑SQL转换器将足够聪明以应对!)类型推断是可以的:

var orders = FoodOrders.Where(o => o.STATUS == 1)
                       .OrderByDescending(o => o.ORDER_DATE)
                       .Select(o => o);

// if customer id is specified, only select orders from specific customer
if (customerID!=null)
{
    orders = orders.Where(o => customerID.Equals(o.CUSTOMER_ID));
}
Run Code Online (Sandbox Code Playgroud)

或者作为最终和略微奇怪的建议,您可以更改初始whereorderby子句的顺序.这在LINQ to Objects中是一个坏主意,但不应该在LINQ to SQL中有所作为:

var orders = from o in FoodOrders
             order by o.ORDER_DATE descending
             where o.STATUS == 1
             select o;

// if customer id is specified, only select orders from specific customer
if (customerID!=null)
{
    orders = orders.Where(o => customerID.Equals(o.CUSTOMER_ID));
}
Run Code Online (Sandbox Code Playgroud)

现在,就API设计的"原因"而言:OrderBy并且OrderByDescending返回IOrderedQueryable以便您可以将其链接起来,ThenByThenByDescending依赖于现有的订单,如果您看到我的意思,它们可以成为次要的.