Klauzula From (odwołanie w C#)from clause (C# Reference)

Wyrażenie zapytania musi zaczynać się od from klauzuli.A query expression must begin with a from clause. Ponadto wyrażenie zapytania może zawierać podzapytaniach, które również zaczynają się od from klauzuli.Additionally, a query expression can contain sub-queries, which also begin with a from clause. from Klauzula określa następujące czynności:The from clause specifies the following:

  • Źródło danych, na którym uruchomiona jest zapytaniu lub podzapytaniu.The data source on which the query or sub-query will be run.

  • Lokalny zmiennej zakresu reprezentujący każdego elementu w sekwencji źródłowej.A local range variable that represents each element in the source sequence.

Zmienna zakresu i źródła danych są silnie typizowane.Both the range variable and the data source are strongly typed. Źródło danych, do którego odwołuje się from klauzula musi mieć typ IEnumerable, IEnumerable<T>, lub typ pochodny, takie jak IQueryable<T>.The data source referenced in the from clause must have a type of IEnumerable, IEnumerable<T>, or a derived type such as IQueryable<T>.

W poniższym przykładzie numbers jest źródłem danych i num jest zmiennej zakresu.In the following example, numbers is the data source and num is the range variable. Należy pamiętać, że obie zmienne są silnie typizowane mimo var słowo kluczowe jest używane.Note that both variables are strongly typed even though the var keyword is used.

class LowNums
{
    static void Main()
    {   
        // A simple data source.
        int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

        // Create the query.
        // lowNums is an IEnumerable<int>
        var lowNums = from num in numbers
            where num < 5
            select num;

        // Execute the query.
        foreach (int i in lowNums)
        {
            Console.Write(i + " ");
        }
    }        
}
// Output: 4 1 3 2 0

Zmienna zakresuThe range variable

Kompilator wnioskuje typ zmiennej zakresu, gdy źródło danych implementuje IEnumerable<T>.The compiler infers the type of the range variable when the data source implements IEnumerable<T>. Na przykład, jeśli źródło ma typ IEnumerable<Customer>, a następnie wywnioskowana jest zmienna zakresu można Customer.For example, if the source has a type of IEnumerable<Customer>, then the range variable is inferred to be Customer. Jedyną sytuacją, który musi określać typ jawnie jest, gdy źródłem jest nieogólnego IEnumerable wpisz na przykład ArrayList.The only time that you must specify the type explicitly is when the source is a non-generic IEnumerable type such as ArrayList. Aby uzyskać więcej informacji, zobacz jak: Zapytanie w ArrayList za pomocą LINQ.For more information, see How to: Query an ArrayList with LINQ.

W poprzednim przykładzie num jest wnioskowany typ int.In the previous example num is inferred to be of type int. Ponieważ zmienna zakresu zdecydowanie jest wpisane, można wywoływać metody na nim lub używać go w innych operacji.Because the range variable is strongly typed, you can call methods on it or use it in other operations. Na przykład zamiast zapisywania select num, można napisać select num.ToString() spowodować wyrażenia zapytania w celu zwrócenia sekwencji, a nie liczby całkowite.For example, instead of writing select num, you could write select num.ToString() to cause the query expression to return a sequence of strings instead of integers. Lub możesz napisać select num + 10 spowodować wyrażenia w celu zwrócenia sekwencji 14, 11, 13, 12, 10.Or you could write select num + 10 to cause the expression to return the sequence 14, 11, 13, 12, 10. Aby uzyskać więcej informacji, zobacz klauzuli select.For more information, see select clause.

Zmienna zakresu jest podobna do zmiennej iteracji w foreach instrukcji, z wyjątkiem jednego bardzo istotną różnicą: zmienną zakresu faktycznie nigdy nie przechowuje dane ze źródła.The range variable is like an iteration variable in a foreach statement except for one very important difference: a range variable never actually stores data from the source. Jest po prostu składni wygody umożliwiająca zapytania do opisywania, co program ma miejsce w przypadku, gdy zapytanie jest wykonywane.It's just a syntactic convenience that enables the query to describe what will occur when the query is executed. Aby uzyskać więcej informacji, zobacz wprowadzenie do zapytań LINQ (C#).For more information, see Introduction to LINQ Queries (C#).

Złożone z klauzulCompound from clauses

W niektórych przypadkach każdego elementu w sekwencji źródłowej sam jest sekwencją albo lub zawiera sekwencję.In some cases, each element in the source sequence may itself be either a sequence or contain a sequence. Na przykład źródła danych może być IEnumerable<Student> gdzie każdy obiekt dla uczniów w sekwencji zawiera listę wyniki testów.For example, your data source may be an IEnumerable<Student> where each student object in the sequence contains a list of test scores. Dostępu do wewnętrznej listy w ramach każdej Student elementu, można użyć złożonego from klauzul.To access the inner list within each Student element, you can use compound from clauses. Technika działa jak przy użyciu zagnieżdżonych foreach instrukcji.The technique is like using nested foreach statements. Możesz dodać gdzie lub orderby klauzule albo from klauzuli do filtrowania wyników.You can add where or orderby clauses to either from clause to filter the results. W poniższym przykładzie przedstawiono sekwencję Student obiektów, z których każdy zawiera wewnętrzny List liczb całkowitych reprezentujących wyników testów.The following example shows a sequence of Student objects, each of which contains an inner List of integers representing test scores. Aby uzyskać dostęp do wewnętrznej listy, należy użyć związek from klauzuli.To access the inner list, use a compound from clause. Możesz wstawić klauzule między tymi dwoma from klauzul, jeśli to konieczne.You can insert clauses between the two from clauses if necessary.

class CompoundFrom
{
    // The element type of the data source.
    public class Student
    {
        public string LastName { get; set; }
        public List<int> Scores {get; set;}
    }

    static void Main()
    {
        
        // Use a collection initializer to create the data source. Note that 
        // each element in the list contains an inner sequence of scores.
        List<Student> students = new List<Student>
        {
           new Student {LastName="Omelchenko", Scores= new List<int> {97, 72, 81, 60}},
           new Student {LastName="O'Donnell", Scores= new List<int> {75, 84, 91, 39}},
           new Student {LastName="Mortensen", Scores= new List<int> {88, 94, 65, 85}},
           new Student {LastName="Garcia", Scores= new List<int> {97, 89, 85, 82}},
           new Student {LastName="Beebe", Scores= new List<int> {35, 72, 91, 70}} 
        };        

        // Use a compound from to access the inner sequence within each element.
        // Note the similarity to a nested foreach statement.
        var scoreQuery = from student in students
                         from score in student.Scores
                            where score > 90
                            select new { Last = student.LastName, score };
                    
        // Execute the queries.
        Console.WriteLine("scoreQuery:");
        // Rest the mouse pointer on scoreQuery in the following line to 
        // see its type. The type is IEnumerable<'a>, where 'a is an 
        // anonymous type defined as new {string Last, int score}. That is,
        // each instance of this anonymous type has two members, a string 
        // (Last) and an int (score).
        foreach (var student in scoreQuery)
        {
            Console.WriteLine("{0} Score: {1}", student.Last, student.score);
        }
        
        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }       
}
/*
scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
*/

Wykonywanie sprzężeń za pomocą wielu z klauzulUsing Multiple from Clauses to Perform Joins

Związek from klauzuli umożliwia dostęp do wewnętrznego kolekcji w jednym źródle danych.A compound from clause is used to access inner collections in a single data source. Jednak zapytanie może również zawierać wiele from klauzul, które generują zapytania uzupełniające ze źródeł danych niezależnych.However, a query can also contain multiple from clauses that generate supplemental queries from independent data sources. Ta technika pozwala na wykonywanie pewnych operacji łączenia, która nie jest możliwa przy użyciu klauzuli join.This technique enables you to perform certain types of join operations that are not possible by using the join clause.

W poniższym przykładzie pokazano jak dwa from klauzule może służyć w celu utworzenia pełne sprzężenie krzyżowe z dwoma źródłami danych.The following example shows how two from clauses can be used to form a complete cross join of two data sources.

class CompoundFrom2
{
    static void Main()
    {
        char[] upperCase = { 'A', 'B', 'C' };
        char[] lowerCase = { 'x', 'y', 'z' };

        // The type of joinQuery1 is IEnumerable<'a>, where 'a
        // indicates an anonymous type. This anonymous type has two
        // members, upper and lower, both of type char.
        var joinQuery1 =
            from upper in upperCase
            from lower in lowerCase
            select new { upper, lower };

        // The type of joinQuery2 is IEnumerable<'a>, where 'a
        // indicates an anonymous type. This anonymous type has two
        // members, upper and lower, both of type char.
        var joinQuery2 =
            from lower in lowerCase
            where lower != 'x'
            from upper in upperCase
            select new { lower, upper };


        // Execute the queries.
        Console.WriteLine("Cross join:");
        // Rest the mouse pointer on joinQuery1 to verify its type.
        foreach (var pair in joinQuery1)
        {
            Console.WriteLine("{0} is matched to {1}", pair.upper, pair.lower);
        }

        Console.WriteLine("Filtered non-equijoin:");
        // Rest the mouse pointer over joinQuery2 to verify its type.
        foreach (var pair in joinQuery2)
        {
            Console.WriteLine("{0} is matched to {1}", pair.lower, pair.upper);
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
        Cross join:
        A is matched to x
        A is matched to y
        A is matched to z
        B is matched to x
        B is matched to y
        B is matched to z
        C is matched to x
        C is matched to y
        C is matched to z
        Filtered non-equijoin:
        y is matched to A
        y is matched to B
        y is matched to C
        z is matched to A
        z is matched to B
        z is matched to C
        */

Aby uzyskać więcej informacji na temat operacji łączenia, które używają wielu from zdań, zobacz wykonaj Lewe sprzężenia zewnętrzne.For more information about join operations that use multiple from clauses, see Perform left outer joins.

Zobacz takżeSee also