Abfrageausdrücke (F#)
Abfrageausdrücke ermöglichen es Ihnen, eine Datenquelle abzufragen und die Daten in eine gewünschte Form einzufügen.Abfrageausdrücke bieten Unterstützung für LINQ in F#.
query { expression }
Hinweise
Abfrageausdrücke sind ein Berechnungsausdruck " ähnlich den Sequenzausdrücken.So wie Sie eine Sequenz angeben, indem Sie Code in einem Sequenzausdruck bereitstellen, geben Sie einen Satz von Daten an, indem Sie Code in einem Abfrageausdruck bereitstellen.In einem Sequenzausdruck identifiziert das yield-Schlüsselwort die als Teil der resultierenden Sequenz zurückgegeben werden Daten.In Abfrageausdrücken akzeptiert das - Schlüsselwort select dieselben Funktionen durch.Zusätzlich zum select-Schlüsselwort F# unterstützt auch einige Abfrageoperatoren, die ähnlich wie die Teile einer SQL SELECT-Anweisung sind.Im Folgenden ein Beispiel eines einfachen Abfrageausdrucks, zusammen mit Code, der an die Quelle OData Northwind herstellt.
// Use the OData type provider to create types that can be used to access the Northwind database.
// Add References to FSharp.Data.TypeProviders and System.Data.Services.Client
open Microsoft.FSharp.Data.TypeProviders
type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc">
let db = Northwind.GetDataContext()
// A query expression.
let query1 = query { for customer in db.Customers do
select customer }
query1
|> Seq.iter (fun customer -> printfn "Company: %s Contact: %s" customer.CompanyName customer.ContactName)
Im vorherigen Codebeispiel ist der Abfrageausdruck in geschweiften Klammern.Die Bedeutung des Codes im Ausdruck ist, gibt alle Kunden in der Tabelle Customers der Datenbank in den Abfrageergebnissen zurück.Abfrageausdrücke geben einen Typ, der IQueryable<T> und IEnumerable<T> implementiert zurück, und daher können sie mit Folgendes Modul als Beispiel die durchlaufen werden.
Jeder Berechnungsausdrucktyps wird von einer Generatorklasse erstellt.Die Generatorklasse für den Abfragenberechnungsausdruck ist QueryBuilder.Weitere Informationen finden Sie unter Berechnungsausdrücke (F#) und Linq.QueryBuilder-Klasse (F#).
Abfrageoperatoren
Abfrageoperatoren aktivieren Sie, um die Details der Abfrage, wie anzugeben, um Kriterien auf die zurückgegeben werden Datensätze zu setzen, geben die Sortierreihenfolge der Ergebnisse an.Die Abfragenquelle muss den Abfrageoperator unterstützen.Wenn Sie versuchen, einen nicht unterstützten Abfrageoperator zu verwenden, wird NotSupportedException ausgelöst.
Nur Ausdrücke, die auf SQL übersetzt werden können, werden in Abfrageausdrücken zulässig.Beispielsweise werden keine Funktionsaufrufe in Ausdrücken zulässig, wenn Sie den where-Abfrageoperator verwenden.
Verfügbare Abfrageoperatoren der zeigt der Tabelle 1.Außerdem finden Sie Tabelle2, das SQL-Abfragen und die entsprechenden F#-Abfrageausdrücke weiter unten in diesem Thema vergleicht.Einige Abfrageoperatoren werden nicht von mehreren Typanbieter unterstützt.Insbesondere wird der OData-Typanbieter in den Abfrageoperatoren beschränkt, die er aufgrund der Einschränkungen in OData unterstützt.Weitere Informationen finden Sie unter ODataService-Typanbieter (F#).
Diese Tabelle ist eine Datenbank im folgenden Format an:
Beispieldatenbank-Diagramm
Der Code in Tabellen, die auch folgen, nimmt den folgenden Datenbankverbindungscode an.Projekte sollten Verweise auf System.Data, System.Data.Linq- und FSharp.Data.TypeProviders-Assemblys hinzufügen.Der Code, der diese Datenbank erstellt, wird am Ende dieses Themas enthalten.
open System
open Microsoft.FSharp.Data.TypeProviders
open System.Data.Linq.SqlClient
open System.Linq
open Microsoft.FSharp.Linq
type schema = SqlDataConnection<"Data Source=SERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = schema.GetDataContext()
// Needed for some query operator examples:
let data = [ 1; 5; 7; 11; 18; 21]
Tabelle 1.Abfrageoperatoren
Operator |
Beschreibung |
contains |
Bestimmt, ob die ausgewählten Elemente ein angegebenes Element enthalten.
|
count |
Gibt die Anzahl der ausgewählten Elemente zurück.
|
last |
Wählt das letzte Element von denen aus, die bisher ausgewählt werden.
|
lastOrDefault |
Wählt das letzte Element von denen aus, die bisher ausgewählt werden, oder einen Standardwert, wenn kein Element gefunden wird.
|
exactlyOne |
Wählt das einzelne, bestimmte Element aus, das bis jetzt ausgewählt ist.Wenn mehrere Elemente vorhanden sind, wird eine Ausnahme ausgelöst.
|
exactlyOneOrDefault |
Wählt das einzelne, von denen bestimmte Element aus, die bisher ausgewählt werden, oder einen Standardwert, wenn dieses Element nicht gefunden wird.
|
headOrDefault |
Wählt das erste Element von denen aus, die bisher ausgewählt werden, oder einen Standardwert, wenn die Sequenz keine Elemente enthält.
|
select |
Projiziert jedes der Elemente, die bisher ausgewählt werden.
|
where |
Markiert Elemente auf Grundlage eines angegebenen Prädikat aus.
|
minBy |
Wählt einen Wert für jedes Element aus, das bis jetzt ausgewählt wird und den minimalen resultierenden Wert zurück.
|
maxBy |
Wählt einen Wert für jedes Element aus, das bis jetzt ausgewählt ist und gibt den maximalen resultierenden Wert zurück.
|
groupBy |
Gruppiert die Elemente, die bisher nach Ansicht eines Selektors des angegebenen Schlüssels ausgewählt werden.
|
sortBy |
Sortiert die Elemente, die bisher in aufsteigender Reihenfolge von der angegebenen Sortierungstaste ausgewählt werden.
|
sortByDescending |
Sortiert die Elemente bis jetzt, die in absteigender Reihenfolge von der angegebenen Sortierungstaste ausgewählt werden.
|
thenBy |
Führt eine folgende Reihenfolge der Elemente aus, die bisher in aufsteigender Reihenfolge von der angegebenen Sortierungstaste ausgewählt werden.Dieser Operator wird nur nach sortBy, sortByDescending, thenBy oder thenByDescending verwendet werden.
|
thenByDescending |
Führt eine folgende Reihenfolge der Elemente aus, die bisher in absteigender Reihenfolge von der angegebenen Sortierungstaste ausgewählt werden.Dieser Operator wird nur nach sortBy, sortByDescending, thenBy oder thenByDescending verwendet werden.
|
groupValBy |
Wählt einen Wert für jedes Element aus, das bis jetzt ausgewählt ist und gruppiert die Elemente durch die angegebene Schlüssel.
|
join |
bereitstellt zwei Gruppen von ausgewählten Werte anhand übereinstimmender Schlüssel.Beachten Sie, dass die Reihenfolge der Schlüssel um = in einen Joinausdruck ist wichtig signieren.In allen Joins wenn die Zeile nach dem -> Symbol geteilt wird, muss der Einzug bis zu dem - Schlüsselwort for mindestens eingezogen werden.
|
groupJoin |
bereitstellt zwei Gruppen von ausgewählten Werte anhand übereinstimmender Schlüssel und Gruppen die Ergebnisse.Beachten Sie, dass die Reihenfolge der Schlüssel um = in einen Joinausdruck ist wichtig signieren.
|
leftOuterJoin |
bereitstellt zwei Gruppen von ausgewählten Werte anhand übereinstimmender Schlüssel und Gruppen die Ergebnisse.Wenn eine beliebige Gruppe leer ist, wird stattdessen eine Gruppe mit einem einzigen Standardwert verwendet.Beachten Sie, dass die Reihenfolge der Schlüssel um = in einen Joinausdruck ist wichtig signieren.
|
sumByNullable |
Wählt einen auf NULL festlegbaren Wert für jedes Element aus, das bis jetzt ausgewählt wird und die Summe dieser Werte zurück.NULL-Werte, die nicht über einen Wert verfügen, werden ignoriert.
|
minByNullable |
Wählt einen auf NULL festlegbaren Wert für jedes Element aus, das bis jetzt ausgewählt wird und die minimalen dieser Werte zurück.NULL-Werte, die nicht über einen Wert verfügen, werden ignoriert.
|
maxByNullable |
Wählt einen auf NULL festlegbaren Wert für jedes Element aus, das bis jetzt ausgewählt wird und das Maximum dieser Werte zurück.NULL-Werte, die nicht über einen Wert verfügen, werden ignoriert.
|
averageByNullable |
Wählt einen auf NULL festlegbaren Wert für jedes Element aus, das bis jetzt ausgewählt und gibt den Durchschnitt dieser Werte zurück.NULL-Werte, die nicht über einen Wert verfügen, werden ignoriert.
|
averageBy |
Wählt einen Wert für jedes Element aus, das bis jetzt ausgewählt und gibt den Durchschnitt dieser Werte zurück.
|
distinct |
Wählt unterschiedliche Elemente von Elementen aus, die bisher ausgewählt werden.
|
exists |
Bestimmt, ob jedes Element, das bis jetzt ausgewählt ist, eine Bedingung erfüllt.
|
find |
Wählt das erste Element aus, das bis jetzt ausgewählt wird, das eine angegebene Bedingung erfüllt.
|
all |
Bestimmt, ob alle Elemente, die bisher ausgewählt werden, eine Bedingung erfüllen.
|
head |
Wählt das erste Element von denen aus, die bisher ausgewählt werden.
|
nth |
Wählt das Element zu einem angegebenen Index unter denen aus, die bisher ausgewählt werden.
|
skip |
Überspringt eine angegebene Anzahl der Elemente, die bisher ausgewählt werden und anschließend die verbleibenden Elemente aus.
|
skipWhile |
Überspringt Elemente einer Sequenz, solange eine angegebene Bedingung zutrifft und anschließend die verbleibenden Elemente aus.
|
sumBy |
Wählt einen Wert für jedes Element aus, das bis jetzt ausgewählt wird und die Summe dieser Werte zurück.
|
take |
Wählt eine angegebene Anzahl zusammenhängender Elemente von denen aus, die bisher ausgewählt werden.
|
takeWhile |
Markiert Elemente aus einer Sequenz, solange eine angegebene Bedingung erfüllt ist, und überspringt dann die verbleibenden Elemente.
|
sortByNullable |
Sortiert die Elemente, die bisher in aufsteigender Reihenfolge von der angegebenen auf NULL festlegbare Sortierungstaste ausgewählt werden.
|
sortByNullableDescending |
Sortiert die Elemente bis jetzt, die in absteigender Reihenfolge von der angegebenen auf NULL festlegbare Sortierungstaste ausgewählt werden.
|
thenByNullable |
Führt eine folgende Reihenfolge der Elemente aus, die bisher in aufsteigender Reihenfolge von der angegebenen auf NULL festlegbare Sortierungstaste ausgewählt werden.Dieser Operator nur wird sofort nach sortBy, sortByDescending, thenBy oder thenByDescending oder ihre auf NULL festlegbaren Varianten verwendet werden.
|
thenByNullableDescending |
Führt eine folgende Reihenfolge der Elemente aus, die bisher in absteigender Reihenfolge von der angegebenen auf NULL festlegbare Sortierungstaste ausgewählt werden.Dieser Operator nur wird sofort nach sortBy, sortByDescending, thenBy oder thenByDescending oder ihre auf NULL festlegbaren Varianten verwendet werden.
|
Vergleich von Transact-SQL und von F#-Abfrageausdrücken
In der folgenden Tabelle werden einige allgemeine Transact-SQL-Abfragen und ihre Äquivalente in F# an.Der Code in dieser Tabelle ist auch die gleiche Datenbank an, die in der vorherigen Tabelle und der gleiche ursprüngliche Code, um den Typanbieters zu installieren.
Tabelle 2.Transact-SQL und F#-Abfrageausdrücke
Der folgende Code kann verwendet werden, um die Beispieldatenbank für diese Beispiele zu erstellen.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
USE [master];
GO
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'MyDatabase')
DROP DATABASE MyDatabase;
GO
-- Create the MyDatabase database.
CREATE DATABASE MyDatabase COLLATE SQL_Latin1_General_CP1_CI_AS;
GO
-- Specify a simple recovery model
-- to keep the log growth to a minimum.
ALTER DATABASE MyDatabase
SET RECOVERY SIMPLE;
GO
USE MyDatabase;
GO
CREATE TABLE [dbo].[Course] (
[CourseID] INT NOT NULL,
[CourseName] NVARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([CourseID] ASC)
);
CREATE TABLE [dbo].[Student] (
[StudentID] INT NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Age] INT NULL,
PRIMARY KEY CLUSTERED ([StudentID] ASC)
);
CREATE TABLE [dbo].[CourseSelection] (
[ID] INT NOT NULL,
[StudentID] INT NOT NULL,
[CourseID] INT NOT NULL,
PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_CourseSelection_ToTable] FOREIGN KEY ([StudentID]) REFERENCES [dbo].[Student] ([StudentID]) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT [FK_CourseSelection_Course_1] FOREIGN KEY ([CourseID]) REFERENCES [dbo].[Course] ([CourseID]) ON DELETE NO ACTION ON UPDATE NO ACTION
);
CREATE TABLE [dbo].[LastStudent] (
[StudentID] INT NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Age] INT NULL,
PRIMARY KEY CLUSTERED ([StudentID] ASC)
);
-- Insert data into the tables.
USE MyDatabase
INSERT INTO Course (CourseID, CourseName)
VALUES(1, 'Algebra I');
INSERT INTO Course (CourseID, CourseName)
VALUES(2, 'Trigonometry');
INSERT INTO Course (CourseID, CourseName)
VALUES(3, 'Algebra II');
INSERT INTO Course (CourseID, CourseName)
VALUES(4, 'History');
INSERT INTO Course (CourseID, CourseName)
VALUES(5, 'English');
INSERT INTO Course (CourseID, CourseName)
VALUES(6, 'French');
INSERT INTO Course (CourseID, CourseName)
VALUES(7, 'Chinese');
INSERT INTO Student (StudentID, Name, Age)
VALUES(1, 'Abercrombie, Kim', 10);
INSERT INTO Student (StudentID, Name, Age)
VALUES(2, 'Abolrous, Hazen', 14);
INSERT INTO Student (StudentID, Name, Age)
VALUES(3, 'Hance, Jim', 12);
INSERT INTO Student (StudentID, Name, Age)
VALUES(4, 'Adams, Terry', 12);
INSERT INTO Student (StudentID, Name, Age)
VALUES(5, 'Hansen, Claus', 11);
INSERT INTO Student (StudentID, Name, Age)
VALUES(6, 'Penor, Lori', 13);
INSERT INTO Student (StudentID, Name, Age)
VALUES(7, 'Perham, Tom', 12);
INSERT INTO Student (StudentID, Name, Age)
VALUES(8, 'Peng, Yun-Feng', NULL);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(1, 1, 2);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(2, 1, 3);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(3, 1, 5);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(4, 2, 2);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(5, 2, 5);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(6, 2, 6);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(7, 2, 3);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(8, 3, 2);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(9, 3, 1);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(10, 4, 2);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(11, 4, 5);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(12, 4, 2);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(13, 5, 3);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(14, 5, 2);
INSERT INTO CourseSelection (ID, StudentID, CourseID)
VALUES(15, 7, 3);
Der folgende Code enthält den Beispielcode, der in diesem Thema angezeigt wird.
#if INTERACTIVE
#r "FSharp.Data.TypeProviders.dll"
#r "System.Data.dll"
#r "System.Data.Linq.dll"
#endif
open System
open Microsoft.FSharp.Data.TypeProviders
open System.Data.Linq.SqlClient
open System.Linq
[<Generate>]
type schema = SqlDataConnection<"Data Source=SERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = schema.GetDataContext()
let student = db.Student
let data = [1; 5; 7; 11; 18; 21]
open System
type Nullable<'T when 'T : ( new : unit -> 'T) and 'T : struct and 'T :> ValueType > with
member this.Print() =
if (this.HasValue) then this.Value.ToString()
else "NULL"
printfn "\ncontains query operator"
query {
for student in db.Student do
select student.Age.Value
contains 11
}
|> printfn "Is at least one student age 11? %b"
printfn "\ncount query operator"
query {
for student in db.Student do
select student
count
}
|> printfn "Number of students: %d"
printfn "\nlast query operator."
let num =
query {
for number in data do
sortBy number
last
}
printfn "Last number: %d" num
open Microsoft.FSharp.Linq
printfn "\nlastOrDefault query operator."
query {
for number in data do
sortBy number
lastOrDefault
}
|> printfn "lastOrDefault: %d"
printfn "\nexactlyOne query operator."
let student2 =
query {
for student in db.Student do
where (student.StudentID = 1)
select student
exactlyOne
}
printfn "Student with StudentID = 1 is %s" student2.Name
printfn "\nexactlyOneOrDefault query operator."
let student3 =
query {
for student in db.Student do
where (student.StudentID = 1)
select student
exactlyOneOrDefault
}
printfn "Student with StudentID = 1 is %s" student3.Name
printfn "\nheadOrDefault query operator."
let student4 =
query {
for student in db.Student do
select student
headOrDefault
}
printfn "head student is %s" student4.Name
printfn "\nselect query operator."
query {
for student in db.Student do
select student
}
|> Seq.iter (fun student -> printfn "StudentID, Name: %d %s" student.StudentID student.Name)
printfn "\nwhere query operator."
query {
for student in db.Student do
where (student.StudentID > 4)
select student
}
|> Seq.iter (fun student -> printfn "StudentID, Name: %d %s" student.StudentID student.Name)
printfn "\nminBy query operator."
let student5 =
query {
for student in db.Student do
minBy student.StudentID
}
printfn "\nmaxBy query operator."
let student6 =
query {
for student in db.Student do
maxBy student.StudentID
}
printfn "\ngroupBy query operator."
query {
for student in db.Student do
groupBy student.Age into g
select (g.Key, g.Count())
}
|> Seq.iter (fun (age, count) -> printfn "Age: %s Count at that age: %d" (age.Print()) count)
printfn "\nsortBy query operator."
query {
for student in db.Student do
sortBy student.Name
select student
}
|> Seq.iter (fun student -> printfn "StudentID, Name: %d %s" student.StudentID student.Name)
printfn "\nsortByDescending query operator."
query {
for student in db.Student do
sortByDescending student.Name
select student
}
|> Seq.iter (fun student -> printfn "StudentID, Name: %d %s" student.StudentID student.Name)
printfn "\nthenBy query operator."
query {
for student in db.Student do
where student.Age.HasValue
sortBy student.Age.Value
thenBy student.Name
select student
}
|> Seq.iter (fun student -> printfn "StudentID, Name: %d %s" student.Age.Value student.Name)
printfn "\nthenByDescending query operator."
query {
for student in db.Student do
where student.Age.HasValue
sortBy student.Age.Value
thenByDescending student.Name
select student
}
|> Seq.iter (fun student -> printfn "StudentID, Name: %d %s" student.Age.Value student.Name)
printfn "\ngroupValBy query operator."
query {
for student in db.Student do
groupValBy student.Name student.Age into g
select (g, g.Key, g.Count())
}
|> Seq.iter (fun (group, age, count) ->
printfn "Age: %s Count at that age: %d" (age.Print()) count
group |> Seq.iter (fun name -> printfn "Name: %s" name))
printfn "\n sumByNullable query operator"
query {
for student in db.Student do
sumByNullable student.Age
}
|> (fun sum -> printfn "Sum of ages: %s" (sum.Print()))
printfn "\n minByNullable"
query {
for student in db.Student do
minByNullable student.Age
}
|> (fun age -> printfn "Minimum age: %s" (age.Print()))
printfn "\n maxByNullable"
query {
for student in db.Student do
maxByNullable student.Age
}
|> (fun age -> printfn "Maximum age: %s" (age.Print()))
printfn "\n averageBy"
query {
for student in db.Student do
averageBy (float student.StudentID)
}
|> printfn "Average student ID: %f"
printfn "\n averageByNullable"
query {
for student in db.Student do
averageByNullable (Nullable.float student.Age)
}
|> (fun avg -> printfn "Average age: %s" (avg.Print()))
printfn "\n find query operator"
query {
for student in db.Student do
find (student.Name = "Abercrombie, Kim")
}
|> (fun student -> printfn "Found a match with StudentID = %d" student.StudentID)
printfn "\n all query operator"
query {
for student in db.Student do
all (SqlMethods.Like(student.Name, "%,%"))
}
|> printfn "Do all students have a comma in the name? %b"
printfn "\n head query operator"
query {
for student in db.Student do
head
}
|> (fun student -> printfn "Found the head student with StudentID = %d" student.StudentID)
printfn "\n nth query operator"
query {
for numbers in data do
nth 3
}
|> printfn "Third number is %d"
printfn "\n skip query operator"
query {
for student in db.Student do
skip 1
}
|> Seq.iter (fun student -> printfn "StudentID = %d" student.StudentID)
printfn "\n skipWhile query operator"
query {
for number in data do
skipWhile (number < 3)
select number
}
|> Seq.iter (fun number -> printfn "Number = %d" number)
printfn "\n sumBy query operator"
query {
for student in db.Student do
sumBy student.StudentID
}
|> printfn "Sum of student IDs: %d"
printfn "\n take query operator"
query {
for student in db.Student do
select student
take 2
}
|> Seq.iter (fun student -> printfn "StudentID = %d" student.StudentID)
printfn "\n takeWhile query operator"
query {
for number in data do
takeWhile (number < 10)
}
|> Seq.iter (fun number -> printfn "Number = %d" number)
printfn "\n sortByNullable query operator"
query {
for student in db.Student do
sortByNullable student.Age
select student
}
|> Seq.iter (fun student ->
printfn "StudentID, Name, Age: %d %s %s" student.StudentID student.Name (student.Age.Print()))
printfn "\n sortByNullableDescending query operator"
query {
for student in db.Student do
sortByNullableDescending student.Age
select student
}
|> Seq.iter (fun student ->
printfn "StudentID, Name, Age: %d %s %s" student.StudentID student.Name (student.Age.Print()))
printfn "\n thenByNullable query operator"
query {
for student in db.Student do
sortBy student.Name
thenByNullable student.Age
select student
}
|> Seq.iter (fun student ->
printfn "StudentID, Name, Age: %d %s %s" student.StudentID student.Name (student.Age.Print()))
printfn "\n thenByNullableDescending query operator"
query {
for student in db.Student do
sortBy student.Name
thenByNullableDescending student.Age
select student
}
|> Seq.iter (fun student ->
printfn "StudentID, Name, Age: %d %s %s" student.StudentID student.Name (student.Age.Print()))
printfn "All students: "
query {
for student in db.Student do
select student
}
|> Seq.iter (fun student -> printfn "%s %d %s" student.Name student.StudentID (student.Age.Print()))
printfn "\nCount of students: "
query {
for student in db.Student do
count
}
|> (fun count -> printfn "Student count: %d" count)
printfn "\nExists."
query {
for student in db.Student do
where (query { for courseSelection in db.CourseSelection do
exists (courseSelection.StudentID = student.StudentID) })
select student }
|> Seq.iter (fun student -> printfn "%A" student.Name)
printfn "\n Group by age and count"
query {
for n in db.Student do
groupBy n.Age into g
select (g.Key, g.Count())
}
|> Seq.iter (fun (age, count) -> printfn "%s %d" (age.Print()) count)
printfn "\n Group value by age."
query {
for n in db.Student do
groupValBy n.Age n.Age into g
select (g.Key, g.Count())
}
|> Seq.iter (fun (age, count) -> printfn "%s %d" (age.Print()) count)
printfn "\nGroup students by age where age > 10."
query {
for student in db.Student do
groupBy student.Age into g
where (g.Key.HasValue && g.Key.Value > 10)
select (g, g.Key)
}
|> Seq.iter (fun (students, age) ->
printfn "Age: %s" (age.Value.ToString())
students
|> Seq.iter (fun student -> printfn "%s" student.Name))
printfn "\nGroup students by age and print counts of number of students at each age with more than 1 student."
query {
for student in db.Student do
groupBy student.Age into group
where (group.Count() > 1)
select (group.Key, group.Count())
}
|> Seq.iter (fun (age, ageCount) ->
printfn "Age: %s Count: %d" (age.Print()) ageCount)
printfn "\nGroup students by age and sum ages."
query {
for student in db.Student do
groupBy student.Age into g
let total = query { for student in g do sumByNullable student.Age }
select (g.Key, g.Count(), total)
}
|> Seq.iter (fun (age, count, total) ->
printfn "Age: %d" (age.GetValueOrDefault())
printfn "Count: %d" count
printfn "Total years: %s" (total.ToString()))
printfn "\nGroup students by age and count number of students at each age, and display all with count > 1 in descending order of count."
query {
for student in db.Student do
groupBy student.Age into g
where (g.Count() > 1)
sortByDescending (g.Count())
select (g.Key, g.Count())
}
|> Seq.iter (fun (age, myCount) ->
printfn "Age: %s" (age.Print())
printfn "Count: %d" myCount)
printfn "\n Select students from a set of IDs"
let idList = [1; 2; 5; 10]
let idQuery = query { for id in idList do
select id }
query {
for student in db.Student do
where (idQuery.Contains(student.StudentID))
select student
}
|> Seq.iter (fun student ->
printfn "Name: %s" student.Name)
printfn "\nLook for students with Name match _e%% pattern and take first two."
query {
for student in db.Student do
where (SqlMethods.Like( student.Name, "_e%") )
select student
take 2
}
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\nLook for students with Name matching [abc]%% pattern."
query {
for student in db.Student do
where (SqlMethods.Like( student.Name, "[abc]%") )
select student
}
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\nLook for students with name matching [^abc]%% pattern."
query {
for student in db.Student do
where (SqlMethods.Like( student.Name, "[^abc]%") )
select student
}
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\nLook for students with name matching [^abc]%% pattern and select ID."
query {
for n in db.Student do
where (SqlMethods.Like( n.Name, "[^abc]%") )
select n.StudentID
}
|> Seq.iter (fun id -> printfn "%d" id)
printfn "\n Using Contains as a query filter."
query {
for student in db.Student do
where (student.Name.Contains("a"))
select student
}
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\nSearching for names from a list."
let names = [|"a";"b";"c"|]
query {
for student in db.Student do
if names.Contains (student.Name) then select student }
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\nJoin Student and CourseSelection tables."
query {
for student in db.Student do
join (for selection in db.CourseSelection ->
student.StudentID = selection.StudentID)
select (student, selection)
}
|> Seq.iter (fun (student, selection) -> printfn "%d %s %d" student.StudentID student.Name selection.CourseID)
printfn "\nLeft Join Student and CourseSelection tables."
query {
for student in db.Student do
leftOuterJoin (for selection in db.CourseSelection ->
student.StudentID = selection.StudentID) into result
for selection in result.DefaultIfEmpty() do
select (student, selection)
}
|> Seq.iter (fun (student, selection) ->
let selectionID, studentID, courseID =
match selection with
| null -> "NULL", "NULL", "NULL"
| sel -> (sel.ID.ToString(), sel.StudentID.ToString(), sel.CourseID.ToString())
printfn "%d %s %d %s %s %s" student.StudentID student.Name (student.Age.GetValueOrDefault()) selectionID studentID courseID)
printfn "\nJoin with count"
query {
for n in db.Student do
join (for e in db.CourseSelection -> n.StudentID = e.StudentID)
count
}
|> printfn "%d"
printfn "\n Join with distinct."
query {
for student in db.Student do
join (for selection in db.CourseSelection ->
student.StudentID = selection.StudentID)
distinct
}
|> Seq.iter (fun (student, selection) -> printfn "%s %d" student.Name selection.CourseID)
printfn "\n Join with distinct and count."
query {
for n in db.Student do
join (for e in db.CourseSelection -> n.StudentID = e.StudentID)
distinct
count
}
|> printfn "%d"
printfn "\n Selecting students with age between 10 and 15."
query {
for student in db.Student do
where (student.Age.Value >= 10 && student.Age.Value < 15)
select student
}
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\n Selecting students with age either 11 or 12."
query {
for student in db.Student do
where (student.Age.Value = 11 || student.Age.Value = 12)
select student
}
|> Seq.iter (fun student -> printfn "%s" student.Name)
printfn "\n Selecting students in a certain age range and sorting."
query {
for n in db.Student do
where (n.Age.Value = 12 || n.Age.Value = 13)
sortByNullableDescending n.Age
select n
}
|> Seq.iter (fun student -> printfn "%s %s" student.Name (student.Age.Print()))
printfn "\n Selecting students with certain ages, taking account of possibility of nulls."
query {
for student in db.Student do
where ((student.Age.HasValue && student.Age.Value = 11) ||
(student.Age.HasValue && student.Age.Value = 12))
sortByDescending student.Name
select student.Name
take 2
}
|> Seq.iter (fun name -> printfn "%s" name)
printfn "\n Union of two queries."
module Queries =
let query1 = query {
for n in db.Student do
select (n.Name, n.Age)
}
let query2 = query {
for n in db.LastStudent do
select (n.Name, n.Age)
}
query2.Union (query1)
|> Seq.iter (fun (name, age) -> printfn "%s %s" name (age.Print()))
printfn "\n Intersect of two queries."
module Queries2 =
let query1 = query {
for n in db.Student do
select (n.Name, n.Age)
}
let query2 = query {
for n in db.LastStudent do
select (n.Name, n.Age)
}
query1.Intersect(query2)
|> Seq.iter (fun (name, age) -> printfn "%s %s" name (age.Print()))
printfn "\n Using if statement to alter results for special value."
query {
for student in db.Student do
select (if student.Age.HasValue && student.Age.Value = -1 then
(student.StudentID, System.Nullable<int>(100), student.Age)
else (student.StudentID, student.Age, student.Age))
}
|> Seq.iter (fun (id, value, age) -> printfn "%d %s %s" id (value.Print()) (age.Print()))
printfn "\n Using if statement to alter results special values."
query {
for student in db.Student do
select (if student.Age.HasValue && student.Age.Value = -1 then
(student.StudentID, System.Nullable<int>(100), student.Age)
elif student.Age.HasValue && student.Age.Value = 0 then
(student.StudentID, System.Nullable<int>(100), student.Age)
else (student.StudentID, student.Age, student.Age))
}
|> Seq.iter (fun (id, value, age) -> printfn "%d %s %s" id (value.Print()) (age.Print()))
printfn "\n Multiple table select."
query {
for student in db.Student do
for course in db.Course do
select (student, course)
}
|> Seq.iteri (fun index (student, course) ->
if (index = 0) then printfn "StudentID Name Age CourseID CourseName"
printfn "%d %s %s %d %s" student.StudentID student.Name (student.Age.Print()) course.CourseID course.CourseName)
printfn "\nMultiple Joins"
query {
for student in db.Student do
join courseSelection in db.CourseSelection on
(student.StudentID = courseSelection.StudentID)
join course in db.Course on
(courseSelection.CourseID = course.CourseID)
select (student.Name, course.CourseName)
}
|> Seq.iter (fun (studentName, courseName) -> printfn "%s %s" studentName courseName)
printfn "\nMultiple Left Outer Joins"
query {
for student in db.Student do
leftOuterJoin (for courseSelection in db.CourseSelection ->
student.StudentID = courseSelection.StudentID) into g1
for courseSelection in g1.DefaultIfEmpty() do
leftOuterJoin (for course in db.Course ->
courseSelection.CourseID = course.CourseID) into g2
for course in g2.DefaultIfEmpty() do
select (student.Name, course.CourseName)
}
|> Seq.iter (fun (studentName, courseName) -> printfn "%s %s" studentName courseName)
Die ist hier die voll Ausgabe, wenn dieser Code in F# Interactive ausgeführt wird.