以下代码:
// 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));
}
给了我以下错误:
无法将类型'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();
但我想知道为什么会出现这种限制?设计API的原因是,在使用where
运算符后无法添加order by
约束的原因是什么?
答案 0 :(得分:12)
OrderBy
的返回类型为IOrderedQueryable<T>
,因此这是orders
变量的类型(部分原因是您在结尾处有无操作投影) - 但返回类型Where
只是IQueryable<T>
。基本上你有一个无操作投影和混合的隐式类型局部变量和查询的最后一个活动部分是一个排序,和< / em>然后你想要重新分配变量。基本上,这是一个不愉快的组合。
你可以这样解决:
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));
}
或者,如果您使用点表示法明确地执行了无操作投影(我怀疑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));
}
或者作为一个最终且略显奇怪的建议,您只需更改初始where
和orderby
条款的顺序即可。这在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));
}
现在,就API设计的“原因”而言:OrderBy
和OrderByDescending
返回IOrderedQueryable
,以便您可以使用ThenBy
和{{ 1}}如果你明白我的意思,它依赖于现有的顺序,它们可以成为次要的。
答案 1 :(得分:4)
重要的是要注意var是强类型的并且在编译时被解释。您的第一个代码段基本上与:
相同IOrderedQueryable<FoodOrders> orders = from o in FoodOrders
where o.STATUS = 1
order by o.ORDER_DATE descending
select o;
当你以这种方式编写代码时,很明显为什么你不能将IQueryable分配给声明为IOrderedQueryable的变量。
你不能以与对象
相同的方式来考虑varobject aString = "Testing...";
var bString = "Testing...";
aString = 1; // Works
bString = 1; // Fails because 1 is not a string