from-sats (C#-referens)
Ett frågeuttryck måste börja med en from
sats. Dessutom kan ett frågeuttryck innehålla underfrågor, som också börjar med en from
sats. Satsen from
anger följande:
Datakällan där frågan eller underfrågan ska köras.
En lokal intervallvariabel som representerar varje element i källsekvensen.
Både intervallvariabeln och datakällan skrivs starkt. Datakällan som refereras i from
-satsen måste ha en typ av IEnumerable, IEnumerable<T>eller en härledd typ som IQueryable<T>.
I följande exempel numbers
är datakällan och num
intervallvariabeln. Observera att båda variablerna är starkt skrivna trots att nyckelordet var används.
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
Intervallvariabeln
Kompilatorn härleder typen av intervallvariabel när datakällan implementerar IEnumerable<T>. Om källan till exempel har en typ av IEnumerable<Customer>
, kommer intervallvariabeln att härledas Customer
till . Den enda gången du måste ange typen explicit är när källan är en icke-generisk IEnumerable
typ, till exempel ArrayList. Mer information finns i Köra frågor mot en matrislista med LINQ.
I föregående exempel num
härleds att vara av typen int
. Eftersom intervallvariabeln är starkt skriven kan du anropa metoder på den eller använda den i andra åtgärder. I stället för att skriva kan du till exempel skriva select num
select num.ToString()
så att frågeuttrycket returnerar en sekvens med strängar i stället för heltal. Eller så kan du skriva select num + 10
så att uttrycket returnerar sekvensen 14, 11, 13, 12, 10. Mer information finns i select-sats.
Intervallvariabeln är som en iterationsvariabel i en foreach-instruktion förutom en mycket viktig skillnad: en intervallvariabel lagrar aldrig data från källan. Det är bara en syntaktisk bekvämlighet som gör att frågan kan beskriva vad som händer när frågan körs. Mer information finns i Introduktion till LINQ-frågor (C#).
Sammansatt från satser
I vissa fall kan varje element i källsekvensen vara antingen en sekvens eller innehålla en sekvens. Datakällan kan till exempel vara en IEnumerable<Student>
plats där varje elevobjekt i sekvensen innehåller en lista med testresultat. Om du vill komma åt den inre listan i varje Student
element kan du använda sammansatta from
satser. Tekniken är som att använda kapslade foreach-instruktioner . Du kan lägga till where - eller orderby-satser i endera from
satsen för att filtrera resultatet. I följande exempel visas en sekvens med Student
objekt som var och en innehåller ett inre List
heltal som representerar testresultat. Använd en sammansatt from
sats för att komma åt den inre listan. Du kan infoga satser mellan de två from
satserna om det behövs.
class CompoundFrom
{
// The element type of the data source.
public class Student
{
public required string LastName { get; init; }
public required List<int> Scores {get; init;}
}
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 Student {LastName="Omelchenko", Scores= [97, 72, 81, 60]},
new Student {LastName="O'Donnell", Scores= [75, 84, 91, 39]},
new Student {LastName="Mortensen", Scores= [88, 94, 65, 85]},
new Student {LastName="Garcia", Scores= [97, 89, 85, 82]},
new Student {LastName="Beebe", Scores= [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);
}
}
}
/*
scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
*/
Använda flera från satser för att utföra kopplingar
En sammansatt from
sats används för att komma åt inre samlingar i en enda datakälla. En fråga kan dock också innehålla flera from
satser som genererar kompletterande frågor från oberoende datakällor. Med den här tekniken kan du utföra vissa typer av kopplingsåtgärder som inte är möjliga med hjälp av kopplingssatsen.
I följande exempel visas hur två from
satser kan användas för att skapa en fullständig korskoppling av två datakällor.
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
*/
Mer information om kopplingsåtgärder som använder flera from
satser finns i Utföra yttre kopplingar till vänster.