Wyrażenia kwerend (F#)
Wyrażenia kwerendy umożliwiają kwerenda źródła danych i umieścić dane w żądanej formie.Wyrażenia kwerendy zapewniają obsługi zapytań LINQ w F#.
query { expression }
Uwagi
Wyrażenia kwerendy są rodzajem obliczeń wyrażenia podobnego do wyrażenia sekwencji.Podobnie, jak określa się sekwencji, podając kod w wyrażenie sekwencji, określonej zestaw danych poprzez podanie kodu w wyrażeniu kwerendy.W przypadku wyrażenia sekwencji yield słowa kluczowego identyfikuje dane zwracane jako część wynikowym sekwencji.W wyrażeniach kwerend select słowa kluczowego pełni tę samą funkcję.W uzupełnieniu do select słowa kluczowego, F# obsługuje również wiele operatorów zapytania, które są podobnie jak części instrukcji SQL SELECT.Oto przykład wyrażenia kwerendy prostej, wraz z kodem, który łączy ze źródłem Northwind OData.
// 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)
W poprzednim przykładzie wyrażenie kwerendy jest w nawiasy klamrowe.Znaczenie kodu w wyrażeniu jest, zwrotu każdy klient w tabeli Klienci w bazie danych w wynikach kwerendy.Wyrażenia kwerendy zwracają typ, który implementuje IQueryable i IEnumerable, a więc może się powtórzyć, za pomocą moduł Seq jak pokazano w przykładzie.
Każdy typ wyrażenia obliczeń jest zbudowany z klasy konstruktora.Klasa konstruktora dla wyrażenia obliczeń kwerendy jest QueryBuilder.Aby uzyskać więcej informacji, zobacz Wyrażenia obliczeń (F#) i Linq.QueryBuilder — Klasa (F#).
Operatory zapytań
Operatory kwerendy można określić dane, kwerendy, takie jak umieścić kryteria na rekordy mają być zwrócone lub określić kolejność sortowania wyników.Źródło kwerendy musi obsługiwać operator kwerendy.Jeśli nastąpi próba użycia kwerendy nieobsługiwany operator, NotSupportedException zostanie wyrzucony.
Tylko te wyrażenia, które mogą być tłumaczone SQL są dozwolone w wyrażeniach kwerend.Na przykład, żadne wywołania funkcji są dozwolone w wyrażeniach, korzystając z where operator kwerendy.
Tabela 1 zawiera operatory zapytań dostępne.Co więcej Zobacz tabela2, który porównuje zapytań SQL i równoważne F# kwerendy wyrażeń w dalszej części tego tematu.Niektórzy operatorzy kwerendy nie są obsługiwane przez niektórych dostawców typu.W szczególności dostawca typu OData jest ograniczony operatorów zapytania, które obsługuje ze względu na ograniczenia w OData.Aby uzyskać więcej informacji, zobacz ODataService typu dostawcy (F#).
Tej tabeli przyjęto założenie bazy danych w następującej formie:
Przykładowy Diagram bazy danych
Kod w tabelach, które należy wykonać zakłada też poniższy kod połączenia bazy danych.Projekty należy dodać odwołania do zestawów System.Data, System.Data.Linq i FSharp.Data.TypeProviders.Kod, który tworzy ta baza danych znajduje się na końcu tego tematu.
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]
W tabeli 1.Operatory zapytań
Operator |
Opis |
contains |
Określa, czy wybrane elementy zawierają określonego elementu.
|
count |
Zwraca liczbę zaznaczonych elementów.
|
last |
Zaznacza ostatni element tych stron do tej pory.
|
lastOrDefault |
Zaznacza ostatni element do tej pory Możliwi lub wartość domyślną, jeśli element nie zostanie znaleziony.
|
exactlyOne |
Powoduje zaznaczenie elementu pojedyncze, konkretne wybrane do tej pory.Jeśli występują wiele elementów, jest wyjątek.
|
exactlyOneOrDefault |
Powoduje zaznaczenie elementu pojedyncze, konkretne wybranych do tej pory lub wartość domyślną, jeśli nie można odnaleźć tego elementu.
|
headOrDefault |
Zaznacza pierwszy element do tej pory Możliwi lub wartość domyślną, jeśli sekwencja zawiera żadnych elementów.
|
select |
Projekty, każdy z elementów wybranych do tej pory.
|
where |
Wybiera elementy oparte na określonym predykatu.
|
minBy |
Wybiera wartość dla każdego elementu, wybrany do tej pory i zwraca minimalną wartość wynikową.
|
maxBy |
Wybiera wartość dla każdego elementu, wybrany do tej pory i zwraca maksymalną wartość wynikową.
|
groupBy |
Grupuje elementy do tej pory wybiera się zgodnie z określonym kluczem wyboru.
|
sortBy |
Sortuje elementy zaznaczone do tej pory w kolejności rosnącej przez dany klucz sortowania.
|
sortByDescending |
Sortuje elementy zaznaczone do tej pory w porządku malejącym przez dany klucz sortowania.
|
thenBy |
Wykonuje kolejne kolejność elementów wybranych do tej pory w kolejności rosnącej przez dany klucz sortowania.Ten operator można używać tylko po sortBy, sortByDescending, thenBy, lub thenByDescending.
|
thenByDescending |
Wykonuje kolejne kolejność elementów wybranych do tej pory w porządku malejącym przez dany klucz sortowania.Ten operator można używać tylko po sortBy, sortByDescending, thenBy, lub thenByDescending.
|
groupValBy |
Wybiera wartość dla każdego elementu, wybrany do tej pory i grupuje elementy według podanego klucza.
|
join |
Jest całkowicie skorelowany dwa zestawy wybranych wartości oparta na dopasowanie klucze.Należy zauważyć, że zamówienie kluczy wokół = zarejestrować się w wyrażeniu sprzężenia jest znacząca.W sprzężeniu wszystkich, jeśli linia jest podzielona po -> symbol, wcięcie musi być wcięty co najmniej o ile to słowo kluczowe for.
|
groupJoin |
Dwa zestawy wybranych wartości oparta na dopasowanie kluczy jest całkowicie skorelowany, a następnie grupuje wyniki.Należy zauważyć, że zamówienie kluczy wokół = zarejestrować się w wyrażeniu sprzężenia jest znacząca.
|
leftOuterJoin |
Dwa zestawy wybranych wartości oparta na dopasowanie kluczy jest całkowicie skorelowany, a następnie grupuje wyniki.Jeśli każda grupa jest pusta, grupy z wartością domyślną pojedynczego użyty.Należy zauważyć, że zamówienie kluczy wokół = zarejestrować się w wyrażeniu sprzężenia jest znacząca.
|
sumByNullable |
Wybiera wartość dopuszczający wartość NULL dla każdego elementu, wybrany do tej pory i zwraca sumę tych wartości.Ewentualne dopuszczający wartość null nie ma wartość jest ignorowana.
|
minByNullable |
Wybiera wartość dopuszczający wartość NULL dla każdego elementu, wybrany do tej pory i zwraca wartość minimalną tych wartości.Ewentualne dopuszczający wartość null nie ma wartość jest ignorowana.
|
maxByNullable |
Wybiera pustych wartości dla każdego elementu, wybrany do tej pory i zwraca maksymalną liczbę tych wartości.Ewentualne dopuszczający wartość null nie ma wartość jest ignorowana.
|
averageByNullable |
Wybiera pustych wartości dla każdego elementu, wybrany do tej pory i zwraca średnią z tych wartości.Ewentualne dopuszczający wartość null nie ma wartość jest ignorowana.
|
averageBy |
Wybiera wartość dla każdego elementu, wybrany do tej pory i zwraca średnią z tych wartości.
|
distinct |
Wybiera elementy wyróżniające od elementów wybranych do tej pory.
|
exists |
Określa, czy dowolny element wybrany do tej pory spełnia warunek.
|
find |
Zaznacza pierwszy element wybrany do tej pory, który spełnia określone warunki.
|
all |
Określa, czy wszystkie elementy zaznaczone do tej pory spełniają warunek.
|
head |
Zaznacza pierwszy element z wybranych do tej pory.
|
nth |
Powoduje zaznaczenie elementu określonym indeksem wśród tych wybranych do tej pory.
|
skip |
Pomija określoną liczbę elementów wybranych do tej pory, a następnie wybiera pozostałych elementów.
|
skipWhile |
Omija elementy w sekwencji, tak długo, jak określony warunek jest spełniony, a następnie wybiera pozostałych elementów.
|
sumBy |
Wybiera wartość dla każdego elementu, wybrany do tej pory i zwraca sumę tych wartości.
|
take |
Wybiera określoną liczbę elementów sąsiadujących z zaznaczonymi do tej pory.
|
takeWhile |
Powoduje zaznaczenie elementów z sekwencji, tak długo, jak określony warunek jest prawdziwy, a następnie pomija pozostałe elementy.
|
sortByNullable |
Sortuje elementy zaznaczone do tej pory w kolejności rosnącej przez dany klucz sortowania dopuszczający wartość null.
|
sortByNullableDescending |
Sortuje elementy zaznaczone do tej pory w porządku malejącym przez dany klucz sortowania dopuszczający wartość null.
|
thenByNullable |
Wykonuje kolejne kolejność elementów wybranych do tej pory w kolejności rosnącej przez dany klucz sortowania dopuszczający wartość null.Ten operator może stanowić jedynie zaraz po sortBy, sortByDescending, thenBy, lub thenByDescending, lub ich odmian dopuszczający wartość null.
|
thenByNullableDescending |
Wykonuje kolejne kolejność elementów wybranych do tej pory w porządku malejącym przez dany klucz sortowania dopuszczający wartość null.Ten operator może stanowić jedynie zaraz po sortBy, sortByDescending, thenBy, lub thenByDescending, lub ich odmian dopuszczający wartość null.
|
Porównanie języka Transact-SQL i wyrażenia kwerendy F#
W poniższej tabeli przedstawiono niektóre typowe kwerendy języka Transact-SQL i ich odpowiedniki w F#.Kod w tej tabeli zakłada również tej samej bazy danych jako poprzedniej tabeli i tym samym kodem początkowym Aby skonfigurować dostawcę typu.
Tabela 2.Transact-SQL i wyrażenia kwerendy F#
Poniższy kod może służyć do tworzenia przykładowej bazy danych dla tych przykładów.
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);
Poniższy kod zawiera przykładowy kod, który pojawia się w tym temacie.
#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)
A Oto pełne dane wyjściowe, po uruchomieniu tego kodu w F# interakcyjne.
Zobacz też
Informacje
Linq.QueryBuilder — Klasa (F#)