2010-06-08 31 views
8

Aşağıdaki kodu: SQL'den LINQ - Neden bir ORDER BY sonra bir WHERE kullanamazsınız?

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

bana aşağıdaki hatayı veriyor: Ben sonunda sıralama yaparak hatayı sabit

Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IOrderedQueryable'. An explicit conversion exists (are you missing a cast?)

:

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

Ama merak ediyorum bu sınırlama neden yerinde? API'nin, bir order by operatörünü kullandıktan sonra where kısıtlaması ekleyemeyecek şekilde tasarlanma nedeni nedir?

cevap

12

OrderBy dönüş tipi IOrderedQueryable<T>, bu nedenle bu orders değişken (Sonunda no-op projeksiyona sahip kısmen) tipi var - ama Where dönüş tipi sadece IQueryable<T> olduğunu. Temel olarak, ve no'tur projeksiyonları ile örtük bir yerel değişkeni ve karışımının bir karışımına sahip olursunuz, sorgunun son aktif kısmı bir sipariştir, ve sonra değişkeni yeniden atamak istersiniz. Temelde mutsuz bir kombinasyon.

Böyle saptamak o:

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

Alternatif olarak, hiçbir-op projeksiyon açıkça nokta gösterimi kullanılarak gerçekleştirilen if (SQL çevirmen başa çıkmak için yeterince akıllı olacak şüpheli!) Tür kesmesi olur düzelecek:

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

Ya kesin ve biraz garip öneri olarak

, sadece ilk where ve orderby hükümlerin sırasını değiştirebilir. Bu LINQ nesnelere de kötü bir fikir olurdu, ama LINQ SQL için bir fark yaratmak olmamalı: OrderBy ve OrderByDescending dönüş IOrderedQueryable so: "neden" API tasarım açısından,

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

Şimdi Daha sonra, ThenBy ve ThenByDescending ile zincirleme yapabilirsiniz, bu da, ne demek istediğimi görürseniz, ikincil hale gelebilecekleri bir sipariş olmalarına dayanır.

+0

no-op sorgusu nedir itiraz ediyor aynı şekilde var düşünemiyorum? – MCS

+0

Bu gerçekten kapsamlı bir cevap ve harika bir açıklama. Teşekkürler. – MCS

+0

@MCS: Ben bir no-op projeksiyonunu kastettim - ne demek istediğimi görüyorsanız, sadece orada olanı seçen bir seçim maddesi. –

4

Var'ın güçlü bir şekilde yazıldığını ve derleme zamanında yorumlanacağını not etmek önemlidir. Eğer kodu size IOrderedQueryable olarak ilan bir değişkene bir IQueryable atanamıyor neden belirginleşmektedir bu şekilde yazarken

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

: İlk kod aslında aynı şekilde pasajı.

Sen

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

İlgili konular