2012-05-09 13 views
12

Esempio:Ho davvero bisogno di usare AsQueryable() alla raccolta? Codice

List<Student> Students = new List<Student>() 
{ 
    new Student(101, "Hugo", "Garcia", new List<int>() { 91, 88, 76, 93 }), 
    new Student(102, "Rick", "Adams", new List<int>() { 70, 73, 66, 90 }), 
    new Student(103, "Michael", "Tucker", new List<int>() { 73, 80, 75, 88 }), 
    new Student(104, "Fadi", "Fakhouri", new List<int>() { 82, 75, 66, 84 }), 
    new Student(105, "Peter", "Barrows", new List<int>() { 67, 78, 70, 82 }) 
}; 

var query = from student in Students 
      where student.Marks.AsQueryable().All(m => m > 70) 
      select student; 

foreach (Student student in query) 
{ 
    Console.WriteLine("{0} {1}<br />", student.FirstName, student.LastName); 
} 

Ma se cambio la query per

var query = from student in Students 
      where student.Marks.All(m => m > 70) 
      select student; 

Questo funziona anche e produce lo stesso risultato, quindi qual è la differenza?

+0

Una domanda simile su ['AsEnumerable'] (http://stackoverflow.com/questions/3389855/am-i-misunderstanding-linq-to-sql-asenumerable) – nawfal

risposta

7

IQueryable è richiesto/consigliato per oggetti provenienti da sorgente remota (come da database).

Per le raccolte di memoria non è utile.

AsQueryable viene utilizzato quando l'albero delle espressioni deve essere costruito.

Posso pensare a uno scenario in cui è meglio adattarsi. Nel tuo esempio, supponi di aver bisogno di alcune informazioni dal database in base all'ID studente.

Ora lo studente è in memoria. È necessario attivare la query del database in base all'ID studente.

var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i)); 

Qualsiasi ulteriore operazione sul studentList verrà richiamato da interfaccia IQueryable (espressione query), e recupererà solo i record di origine dati, che deve essere restituito come risultato dell'interrogazione finale (finché origine dati, ritorno valore di remoteDBProvider.GetInfo nell'esempio, supporta QueryProvider).

+5

@BorisB. Questo semplicemente non è vero. [Enumerable.Select] (http://msdn.microsoft.com/en-us/library/bb548891.aspx) utilizza anche l'esecuzione posticipata. La differenza è che Queryable accetta il lambda come espressione. Ciò consente a un provider di query di esaminare l'espressione e tradurla in qualcosa (potenzialmente) più efficiente, ad es. una query SQL. Eventuali proiezioni o filtri verranno eseguiti nel database anziché nell'applicazione, sfruttando il codice nativo del database. Ma per le raccolte in memoria non fa differenza. –

+0

@NielsvanderRest: hai ragione, commento eliminato poiché è fuorviante (o semplicemente falso). Tuttavia, 'AsQueryable' ha ancora i suoi usi anche per le raccolte di memoria, dal momento che il suo metodo di estensione 'Select' accetta un' Expression ', che consente di analizzarlo o modificarlo. Uno scenario a cui posso pensare è quello di utilizzare la raccolta in-memory racchiusa in un 'IQueryable' come un modo per un livello persistente-inconsapevole di inviare una query come un AST a un livello che riconosce la persistenza. –

2

Deve fare come viene costruito l'albero delle espressioni. Guardate questo:

AsQueryable è un metodo che permette la query per essere convertito in un istanza di IQueryable. Quando si utilizza l'operatore AsQueryable su una query esistente e si applicano ulteriori trasformazioni come l'applicazione di un filtro o la specifica di un ordinamento, tali istruzioni lambda sono convertite in alberi Espressione . A seconda del provider che si utilizza , gli alberi di espressione verranno convertiti nella sintassi specifica del dominio e poi eseguiti. Nel caso del provider Linq to SQL, l'albero delle espressioni verrebbe convertito in SQL ed eseguito su server SQL. Tuttavia, se si utilizza l'operatore AsQueryable su una query che non implementa IQueryable e implementi IEnumerable, le eventuali trasformazioni applicate alla query cadono automaticamente sulla specifica IEnumerable. Ciò significa che taggando una query con AsQueryable si ottengono vantaggi sia da Linq a SQL che da Linq all'implementazione dell'oggetto. Se la query esistente si verifica per implementare IQueryable, la query viene convertita in SQL dal provider Linq a SQL, in caso contrario la query viene eseguita in memoria nel modulo IL code.

Riferimento here

1

Nel caso del vostro List<Student>, non fa alcuna differenza, come restituita IQueryable<T> utilizzeranno gli stessi metodi per l'interrogazione, come se non avesse usato AsQueryable() a tutti.

Alcuni metodi prevedono un parametro IQueryable<T>.Penso che il metodo di estensione AsQueryable() sia utile soprattutto per quegli scenari, quando è necessario passare un IQueryable<T> ma solo uno IEnumerable<T>.

MSDN dice su AsQueryable:

Se il tipo di fonte implementa IQueryable<T>, AsQueryable<TElement>(IEnumerable<TElement>) ritorna direttamente. In caso contrario, restituisce un IQueryable<T> che esegue query chiamando i metodi operatore di query equivalenti in Enumerable anziché quelli in Queryable.

Quindi questo significa che nel tuo caso (List<T> non implementa IQueryable<T>), è davvero non hanno bisogno AsQueryable.

Problemi correlati