Domanda

Di seguito sono riportate due query che restituiscono gli stessi dati.A parte lo stile, non sono sicuro di quale sia il migliore.

Quali fattori influenzano queste query?Quali sono i vantaggi dell’utilizzo di uno stile rispetto all’altro?

Campione 1

var x = from s in db.Surveys
    join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
    join q in db.Questions on sq.Question_ID equals q.ID
    join qg in db.Question_Groups on q.ID equals qg.Question_ID
    where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
    select new { question = sq.Question, status = sq.Status, grp = qg };

Campione 2

var x = db.Surveys.Where(s => s.Type_ID.Equals(typeID) & s.Type.Equals(type))
              .Join(db.Survey_Questions,
                        s => s.ID,
                        sq => sq.Survey_ID,
                        (s, sq) => new
                        {
                            question = sq.Question,
                            status = sq.Status
                        })
              .Join(db.Question_Groups,
                        q => q.question.ID,
                        qg => qg.Question_ID,
                        (q, qg) => new
                        {
                            question = q.question,
                            status = q.status,
                            group = qg
                        }).ToList();
È stato utile?

Soluzione

Aggiornamento:. Avete fissato il titolo, in modo da ignorare lo sproloquio

Il titolo della tua domanda non ha nulla a che vedere con i tuoi esempi di codice. La tua domanda implica che una sintassi è IEnumerable e l'altro è IQueryable, ma questo non è corretto. Nei tuoi campioni, se db.Surveys è un IQueryable, allora sia i campioni utilizzano IQueryable. Cercherò di rispondere a sia domande.

I tuoi due esempi di codice sono solo modi diversi di scrivere la stessa query LINQ (ammesso che sono ben scritti). Il codice di esempio 1 è solo scorciatoia per il codice di esempio 2. Il compilatore considera il codice in entrambi i campioni nello stesso modo. Pensate al modo in cui il compilatore C # tratterà int? lo stesso Nullable<System.Int32>. Sia il C # e VB.Net lingue forniscono questa sintassi di query abbreviata. Altre lingue potrebbero non avere questa sintassi e si dovrà utilizzare la sintassi di esempio 2. In realtà, altre lingue non potrebbe anche sostenere i metodi di estensione o espressioni lambda, e si dovrebbe utilizzare una sintassi più brutto ancora.


Aggiornamento:

Per fare l'esempio di Sander ulteriormente, quando si scrive questo (sintassi comprensione query):

var surveyNames = from s in db.Surveys select s.Name

pensare il compilatore giri che abbreviata in questo (metodi di estensione e l'espressione lambda):

IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);

Ma in realtà i metodi di estensione e le espressioni lambda si stanno stenografia. I compilatori emette qualcosa di simile (non esattamente, ma solo per dare un'idea):

Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);

Si noti che Select() è solo un metodo statico nella classe Queryable. Se il linguaggio .NET non supportava la sintassi di query, lambda, o metodi di estensione, che è un pò come si sarebbe dovuto scrivere il codice.


  

Quali sono i vantaggi di utilizzare uno stile sopra l'altro?

Per le piccole domande, metodi di estensione possono essere più compatti:

var items = source.Where(s => s > 5);

Inoltre, la sintassi metodo di estensione può essere più flessibile, come ad esempio condizionale dove clausole:

var items = source.Where(s => s > 5);

if(smallerThanThen)
    items = items.Where(s => s < 10);
if(even)
    items = items.Where(s => (s % 2) == 0);

return items.OrderBy(s => s);

In aggiunta, diversi metodi sono disponibili solo tramite la sintassi metodo di estensione (Count (), Aggregate (), prendere (), Skip (), ToList (), ToArray (), ecc), quindi se userò uno di questi, io di solito scrivere l'intera query in questa sintassi per evitare di mescolare entrambe le sintassi.

var floridaCount = source.Count(s => s.State == "FL");

var items = source
            .Where(s => s > 5)
            .Skip(5)
            .Take(3)
            .ToList();

D'altra parte, quando una query diventa più grande e più complessa, la sintassi di comprensione query può essere più chiaro, soprattutto una volta che si avvia complicare con pochi let, group, join, ecc.

Alla fine io di solito usare a seconda di quale funziona meglio per ogni query specifica.


Aggiornamento: viene confermato il titolo, in modo da ignorare il resto ...

Ora, circa il titolo: Per quanto riguarda LINQ, IEnumerable e IQueryable sono molto simili. Entrambi hanno più o meno gli stessi metodi di estensione (Select, dove, Conte, ecc), con i principali (solo?) Differenza che IEnumerable prende Func<TIn,TOut> come paremeters e IQueryable prende Expression<Func<TIn,TOut>> come parametri. Si esprimono entrambi allo stesso modo (di solito le espressioni Lamba), ma internamente sono completamente diversi.

IEnumerable è la porta per LINQ to Objects. Il LINQ to Objects metodi di estensione può essere chiamato su qualsiasi IEnumerable (array, liste, qualsiasi cosa si può scorrere con foreach) e la Func<TIn,TOut> viene convertita in IL al momento della compilazione e corre come un codice di metodo normale in fase di esecuzione. Si noti che alcuni altri fornitori di LINQ usano IEnumerable e così sono in realtà utilizzando LINQ to Objects dietro le quinte (LINQ to XML, LINQ to DataSet).

IQueryable viene utilizzato da LINQ to SQL, LINQ to Entities, e altri fornitori di LINQ che hanno bisogno di esaminare la query e tradurlo invece di eseguire direttamente il codice. query IQueryable e le loro Expression<Func<TIn,TOut>>s non vengono compilate in IL al momento della compilazione. Invece un albero di espressione is creato e può essere esaminato in fase di esecuzione. Questo permette alle istruzioni che devono essere tradotti in altre lingue query (ad esempio T-SQL). Un albero di espressione può essere compilato in un Func in fase di esecuzione ed eseguito se lo si desidera.

Un esempio che illustra la differenza può essere trovato in questa domanda in cui il PO vuole fare parte di una query LINQ to SQL in SQL Server, portare gli oggetti in codice gestito, e il resto della query in LINQ to Objects. Per raggiungere questo tutto quello che deve fare è lanciare l'IQueryable in un IEnumerable dove vuole l'interruttore per accadere.

Altri suggerimenti

LINQ è la parola buzz per una tecnologia.

IQueryable è un'interfaccia NET che viene utilizzato da LINQ.

Oltre lo stile, non v'è alcuna differenza tra i due. Utilizzare qualsiasi stile che si preferisce.

Io preferisco il primo stile di lunga dichiarazione (come quella mostrata qui) e la seconda per le dichiarazioni molto brevi.

La clausola where nel primo esempio è in realtà lo zucchero sintattico per la clausola Where nel secondo metodo. In realtà, è possibile scrivere la propria classe che non ha nulla a che fare con LINQ o IQueryable e soltanto con un metodo in cui, è possibile utilizzare tale zucchero sintattico. Ad esempio:

    public class MyClass
    {

        public MyClass Where<T>(Func<MyClass, T> predicate)
        {
            return new MyClass { StringProp = "Hello World" };
        }

        public MyClass Select<T>(Func<MyClass, T> predicate)
        {
            return new MyClass ();
        }



        public string StringProp { get; set; }
    }

Questo è ovviamente un esempio stupido, ma nota che c'è un Dove metodo che restituisce solo un nuovo MyClass con stringprop impostato su Ciao Mondo. Per dimostrare:

MyClass a = new MyClass();
            var q = from p in a
                    where p.StringProp == "foo" // doesnt matter what we put here, as we're not really checking the predicate
                    select p;
            Console.WriteLine(q.StringProp);

Questo si tradurrà in scrittura di "Ciao Mondo". Ancora una volta, questo esempio è ovviamente inutile, ma dimostra il punto che la sintassi "dove" sembra proprio per un metodo in cui nel codice che prende una Funz.

espressioni di query e metodi di estensione sono due modi per fare la stessa identica cosa. espressioni di query si trasformano a metodi di estensione durante la compilazione -. sono solo zucchero sintattico per coloro che sono più a suo agio con SQL

Quando si scrive questo:

var surveyNames = from s in db.Surveys select s.Name;

Il compilatore trasforma questo in:

IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);

In realtà, penso che espressioni di query sono stati creati solo per motivi di marketing - un costrutto del linguaggio SQL-like di agire come un eye-catcher quando LINQ è stato sviluppato, non qualcosa che offre molto di effettivo utilizzo. Trovo che la maggior parte delle persone basta usare i metodi di estensione direttamente, quali risultano in uno stile di codifica più unitaria, al posto di un mix di C # e SQL.

1. / Il tuo titolo della domanda non corrisponde a quello che hai chiesto.
2. / Il titolo questione non ha molto senso. Linq acronimo di Language Integrated Query ed è un termine generico per un gruppo di tecnologie e pratiche, IQueryable è un'interfaccia che viene comunemente utilizzato per facilitare LINQ. si confrontano le mele e le arance
3. / A proposito di tua domanda attuale, la differenza principale è in stile, per query complesse come questa, la mia preferenza personale è la seconda versione, come mostra chiaramente la progressione dei set di risultati.

Tuo Campione1 è una rappresentazione di livello superiore di Linq, è più leggibile e durante la compilazione verrà convertito nell'albero delle espressioni, ovvero il tuo Campione2.

var x = from s in db.Surveys
    join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
    join q in db.Questions on sq.Question_ID equals q.ID
    join qg in db.Question_Groups on q.ID equals qg.Question_ID
    where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
    select new { question = sq.Question, status = sq.Status, grp = qg };

puoi provare il codice seguente per ottenere l'espressione per la query scritta

var exp=x.Expression;

Le espressioni vengono utilizzate quando le query sono meno complicate

Credo che la tua domanda è meglio formulata in questo modo: "Qual è la differenza tra IEnumerable e IQueryable rispetto a LINQ"

query LINQ restituiscono un IQueryable per impostazione predefinita. IQueryable consente di aggiungere altri filtri o "clausole" sul vostro query prima lo si esegue.

La vostra query LINQ (primo esempio) e il vostro LINQ utilizzando il concatenamento metodo (secondo esempio) producono lo stesso risultato, con sintassi diversa.

E 'possibile scrivere una query LINQ come metodo catena LINQ e viceversa. Dipende molto dalla vostra preferenza.

@Lucas: Il diverso è IEnumerable fa in memoria interrogazione e IQueryable non out-of-memoria. Che significa, una volta che ci si trova in un iteratore foreach, si utilizza IEnumerable, e quando si sta costruendo la tua ricerca, attraverso sia i metodi di estensione o utilizzando LINQ from o in object synatax, si sta costruendo un IQueryable . L'IQueryable viene eseguito non appena si tocca l'Enumerator.

Un altro punto degno di nota è che i metodi di estensione Linq aderire al linguaggio C #, mentre la roba interrogazione comprensione viene pre-elaborato come è integrato nel compilatore. cioè è possibile passare alla definizione di .Selezionare (x => considerando che non è possibile per from ... where ... select

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top