LINQ к SQL - Почему Вы не можете использовать ГДЕ после ORDER BY?

Следующий код:

// 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 оператор?

9
задан MCS 8 June 2010 в 16:40
поделиться

2 ответа

Тип возврата 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 , которые полагаются на существующее упорядочивание и могут стать вторичными по отношению к , если вы понимаете, о чем я.

13
ответ дан 4 December 2019 в 12:16
поделиться

Важно отметить, что 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

http://msdn.microsoft.com/en-us/library/bb384061.aspx

4
ответ дан 4 December 2019 в 12:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: