Следующий код:
// 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));
}
дает мне следующую ошибку:
Не может неявно преобразовать тип 'Система. Linq. IQueryable' к 'Системе. 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 был разработан таким способом, которым Вы не можете добавить a where
ограничение после использования order by
оператор?
Тип возврата OrderBy
- IOrderedQueryable
, так что это тип переменной orders
(частично потому, что у вас есть проекция без операции в конце) - но тип возвращаемого значения , где
- это просто IQueryable
. По сути, у вас есть смесь безоперационной проекции и неявно типизированной локальной переменной и последней активной частью запроса является упорядочение, и затем вы хотите переназначить переменную. По сути, это неудачная комбинация.
Вы можете исправить это следующим образом:
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
return IOrderedQueryable
, чтобы затем можно было связать его с помощью ThenBy
и ThenByDescending
, которые полагаются на существующее упорядочивание и могут стать вторичными по отношению к , если вы понимаете, о чем я.
Важно отметить, что var строго типизирован и интерпретируется во время компиляции. Ваш первый фрагмент кода, по сути, такой же, как:
IOrderedQueryable<FoodOrders> orders = from o in FoodOrders
where o.STATUS = 1
order by o.ORDER_DATE descending
select o;
Когда вы пишете код таким образом, становится очевидным, почему вы не можете назначить IQueryable переменной, объявленной как IOrderedQueryable.
Вы не можете думать о var так же, как возражали бы
object aString = "Testing...";
var bString = "Testing...";
aString = 1; // Works
bString = 1; // Fails because 1 is not a string