from, clause (Référence C#)
Une expression de requête doit commencer par une clause from. En outre, une expression de requête peut contenir des sous-requêtes qui commencent également par une clause from. La clause from spécifie les éléments suivants :
La source de données sur laquelle la requête ou la sous-requête sera exécutée.
Une variable de portée locale qui représente chaque élément dans la séquence source.
La variable de portée et la source de données sont toutes les deux fortement typées. La source de données référencée dans la clause from doit avoir un type de IEnumerable, IEnumerable<T> ou un type dérivé tel que IQueryable<T>.
Dans l'exemple suivant, numbers est la source de données et num est la variable de portée. Notez que les deux variables sont fortement typées même lorsque le mot clé var est utilisé.
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
Variable de portée
Le compilateur déduit le type de la variable de portée lorsque la source de données implémente IEnumerable<T>. Par exemple, si la source a un type de IEnumerable<Customer>, alors la variable de portée est déduite pour être Customer. Vous devez spécifier le type explicitement uniquement lorsque la source est un type IEnumerable non générique tel que ArrayList. Pour plus d'informations, consultez Comment : interroger un ArrayList avec LINQ.
Dans l'exemple précédent, num est déduit pour être de type int. Comme la variable de portée est fortement typée, vous pouvez appeler des méthodes sur celle-ci ou l'utiliser dans d'autres opérations. Par exemple, au lieu d'écrire select num, vous pourriez écrire select num.ToString() pour que l'expression de requête retourne une séquence de chaînes à la place d'entiers. Vous pouvez également écrire select n + 10 pour que l'expression retourne la séquence 14, 11, 13, 12, 10. Pour plus d'informations, consultez select, clause (Référence C#).
La variable de portée est semblable à une variable d'itération dans une instruction foreach à une différence près qui est importante : une variable de portée ne stocke jamais réellement de données de la source. En termes de syntaxe, son utilisation est simplement plus pratique et elle permet à la requête de décrire ce qui se produira lors de son exécution. Pour plus d'informations, consultez Introduction aux requêtes LINQ (C#).
Clauses from composées
Dans quelques cas, chaque élément dans la séquence source peut être une séquence ou contenir une séquence. Par exemple, votre source de données peut être un IEnumerable<Student> où chaque objet Student dans la séquence contient une liste de notes d'examens. Pour accéder à la liste interne dans chaque élément Student, vous pouvez utiliser des clauses from composées. Cette technique est proche de celle consistant à utiliser des instructions foreach imbriquées. Vous pouvez ajouter des clauses where ou orderby à l'une et l'autre des clauses from pour filtrer les résultats. L'exemple suivant présente une séquence d'objets Student et chacun contient un List interne des entiers qui représentent des notes d'examens. Pour accéder à la liste interne, utilisez une clause from composée. Vous pouvez insérer des clauses entre les deux clauses from si nécessaire.
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
*/
Utilisation de plusieurs clauses pour effectuer des jointures
Une clause from composée est utilisée pour accéder aux collections internes dans une source de données unique. Toutefois, une requête peut également contenir plusieurs clauses from qui génèrent des requêtes supplémentaires de sources de données indépendantes. Cette technique vous permet d'effectuer certains types d'opérations de jointure qui ne sont pas possibles en utilisant la clause de jointure.
L'exemple suivant montre comment utiliser deux clauses from pour former une jointure croisée complète de deux sources de données.
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
*/
Pour plus d'informations sur les opérations de jointure qui utilisent plusieurs clauses from, consultez Comment : effectuer des opérations de jointure personnalisées (Guide de programmation C#).
Voir aussi
Concepts
Expressions de requête LINQ (Guide de programmation C#)