Expressions de requête
Les expressions de requête vous permettent d’interroger une source de données et de placer les données dans la forme souhaitée. Les expressions de requête prennent en charge LINQ en F#.
Syntaxe
query { expression }
Notes
Les expressions de requête sont un type d’expression de calcul similaire aux expressions de séquence. De la même façon que vous spécifiez une séquence en fournissant du code dans une expression de séquence, vous spécifiez un ensemble de données en fournissant du code dans une expression de requête. Dans une expression de séquence, le mot clé yield
identifie les données à renvoyer dans le cadre de la séquence obtenue. Dans les expressions de requête, le mot clé select
exécute la même fonction. En plus du mot clé select
, F# prend également en charge un certain nombre d’opérateurs de requête qui ressemblent beaucoup aux parties d’une instruction SQL SELECT. Voici un exemple d’expression de requête simple, avec du code qui se connecte à la source OData Northwind.
// 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
}
// Print results
query1
|> Seq.iter (fun customer -> printfn "Company: %s Contact: %s" customer.CompanyName customer.ContactName)
Dans l’exemple de code précédent, l’expression de requête est entre accolades. Le sens du code dans l’expression est de renvoyer chaque client de la table Customers de la base de données dans les résultats de requête. Les expressions de requête renvoient un type qui implémente IQueryable<T> et IEnumerable<T>, elles peuvent donc être itérées avec le module Seq comme le montre l’exemple.
Chaque type d’expression de calcul est créé à partir d’une classe de générateur. La classe de générateur de l’expression de calcul de requête est QueryBuilder
. Pour plus d’informations, consultez Expressions de calcul et classe QueryBuilder.
Opérateurs de requête
Les opérateurs de requête vous permettent de spécifier les détails de la requête, par exemple, pour placer des critères sur les enregistrements à renvoyer ou spécifier l’ordre de tri des résultats. La source de requête doit prendre en charge l’opérateur de requête. Si vous tentez d’utiliser un opérateur de requête non pris en charge, l’exception System.NotSupportedException
est levée.
Seules les expressions qui peuvent être traduites en SQL sont autorisées dans les expressions de requête. Par exemple, aucun appel de fonction n’est autorisé dans les expressions si vous utilisez l’opérateur de requête where
.
Le tableau 1 montre les opérateurs de requête disponibles. Par ailleurs, consultez le tableau 2, qui compare les requêtes SQL et les expressions de requête F# équivalentes plus loin dans cette rubrique. Certains opérateurs de requête ne sont pas pris en charge par certains fournisseurs de type. En particulier, le fournisseur de type OData est limité dans les opérateurs de requête qu’il prend en charge en raison de limitations dans OData.
Ce tableau utilise une base de données de la forme suivante :
Le code dans les tableaux qui suivent utilise également le code de connexion aux bases de données suivant. Les projets doivent ajouter des références aux assemblys System.Data, System.Data.Linq et FSharp.Data.TypeProviders. Le code qui crée cette base de données est ajouté à la fin de cette rubrique.
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]
Tableau 1. Opérateurs de requête
Opérateur | Description |
---|---|
contains |
Détermine si les éléments sélectionnés ont un élément spécifié.
|
count | Renvoie le nombre d’éléments sélectionnés.
|
last | Sélectionne le dernier des éléments sélectionnés jusqu’à présent.
|
lastOrDefault | Sélectionne le dernier des éléments sélectionnés jusqu’à présent, ou une valeur par défaut si aucun élément n’est trouvé.
|
exactlyOne | Sélectionne le seul élément spécifique sélectionné jusqu’à présent. Si plusieurs éléments sont présents, une exception est levée.
|
exactlyOneOrDefault | Sélectionne le seul élément spécifique parmi ceux sélectionnés jusqu’à présent, ou une valeur par défaut si cet élément est introuvable.
|
headOrDefault | Sélectionne le premier des éléments sélectionnés jusqu’à présent, ou une valeur par défaut si la séquence ne contient aucun élément.
|
select | Projette chacun des éléments sélectionnés jusqu’à présent.
|
where | Sélectionne les éléments en fonction d’un prédicat spécifié.
|
minBy | Sélectionne une valeur pour chaque élément sélectionné jusqu’à présent et renvoie la valeur minimale obtenue.
|
maxBy | Sélectionne une valeur pour chaque élément sélectionné jusqu’à présent et renvoie la valeur maximale obtenue.
|
groupBy | Regroupe les éléments sélectionnés jusqu’à présent en fonction d’un sélecteur de clé spécifié.
|
sortBy | Trie les éléments sélectionnés jusqu’à présent dans l’ordre croissant en utilisant la clé de tri donnée.
|
sortByDescending | Trie les éléments sélectionnés jusqu’à présent dans l’ordre décroissant en utilisant la clé de tri donnée.
|
thenBy | Effectue un tri ultérieur des éléments sélectionnés jusqu’à présent dans l’ordre croissant en utilisant la clé de tri donnée. Cet opérateur peut être utilisé seulement après sortBy , sortByDescending , thenBy ou thenByDescending .
|
thenByDescending | Effectue un tri ultérieur des éléments sélectionnés jusqu’à présent dans l’ordre décroissant en utilisant la clé de tri donnée. Cet opérateur peut être utilisé seulement après sortBy , sortByDescending , thenBy ou thenByDescending .
|
groupValBy | Sélectionne une valeur pour chaque élément sélectionné jusqu’à présent et regroupe les éléments en fonction de la clé donnée.
|
join | Met en corrélation deux ensembles de valeurs sélectionnées en fonction de clés correspondantes. Notez que l’ordre des clés autour de du signe = dans une expression de jointure est significatif. Dans toutes les jointures, si la ligne est divisée après le symbole -> , la mise en retrait doit être appliquée au moins jusqu’au mot clé for .
|
groupJoin | Met en corrélation deux ensembles de valeurs sélectionnées en fonction des clés correspondantes et regroupe les résultats. Notez que l’ordre des clés autour de du signe = dans une expression de jointure est significatif.
|
leftOuterJoin | Met en corrélation deux ensembles de valeurs sélectionnées en fonction des clés correspondantes et regroupe les résultats. Si un groupe est vide, un groupe avec une seule valeur par défaut est utilisé à la place. Notez que l’ordre des clés autour de du signe = dans une expression de jointure est significatif.
|
sumByNullable | Sélectionne une valeur nullable pour chaque élément sélectionné jusqu’à présent et renvoie la somme de ces valeurs. Si un nullable n’a pas de valeur, il est ignoré.
|
minByNullable | Sélectionne une valeur nullable pour chaque élément sélectionné jusqu’à présent et renvoie la valeur minimale. Si un nullable n’a pas de valeur, il est ignoré.
|
maxByNullable | Sélectionne une valeur nullable pour chaque élément sélectionné jusqu’à présent et renvoie la valeur maximale. Si un nullable n’a pas de valeur, il est ignoré.
|
averageByNullable | Sélectionne une valeur nullable pour chaque élément sélectionné jusqu’à présent et renvoie la moyenne de ces valeurs. Si un nullable n’a pas de valeur, il est ignoré.
|
averageBy | Sélectionne une valeur pour chaque élément sélectionné jusqu’à présent et renvoie la moyenne de ces valeurs.
|
distinct | Sélectionne des éléments distincts parmi les éléments sélectionnés jusqu’à présent.
|
exists | Détermine si un élément sélectionné jusqu’à présent remplit une condition.
|
find | Sélectionne le premier élément sélectionné jusqu’à présent qui remplit une condition spécifiée.
|
all | Détermine si tous les éléments sélectionnés jusqu’à présent remplissent une condition.
|
head | Sélectionne le premier des éléments sélectionnés jusqu’à présent.
|
nth | Sélectionne l’élément à un index spécifié parmi ceux sélectionnés jusqu’à présent.
|
skip | Ignore un nombre spécifié d’éléments sélectionnés jusqu’à présent, puis sélectionne les éléments restants.
|
skipWhile | Ignore des éléments dans une séquence tant que la condition spécifiée a la valeur true, puis sélectionne les éléments restants.
|
sumBy | Sélectionne une valeur pour chaque élément sélectionné jusqu’à présent et renvoie la somme de ces valeurs.
|
take | Sélectionne un nombre spécifié d’éléments contigus parmi ceux sélectionnés jusqu’à présent.
|
takeWhile | Sélectionne des éléments dans une séquence tant que la condition spécifiée a la valeur true, puis ignore les éléments restants.
|
sortByNullable | Trie les éléments sélectionnés jusqu’à présent dans l’ordre croissant en utilisant la clé de tri nullable donnée.
|
sortByNullableDescending | Trie les éléments sélectionnés jusqu’à présent dans l’ordre décroissant en utilisant la clé de tri nullable donnée.
|
thenByNullable | Effectue un tri ultérieur des éléments sélectionnés jusqu’à présent dans l’ordre croissant en utilisant la clé de tri nullable donnée. Cet opérateur peut être utilisé seulement immédiatement après sortBy , sortByDescending , thenBy ou thenByDescending , ou leurs variantes nullables.
|
thenByNullableDescending | Effectue un tri ultérieur des éléments sélectionnés jusqu’à présent dans l’ordre décroissant en utilisant la clé de tri nullable donnée. Cet opérateur peut être utilisé seulement immédiatement après sortBy , sortByDescending , thenBy ou thenByDescending , ou leurs variantes nullables.
|
Comparaison des expressions de requête Transact-SQL et F#
Le tableau suivant montre certaines requêtes Transact-SQL courantes et leurs équivalents en F#. Le code de ce tableau utilise également la même base de données que le tableau précédent et le même code initial pour configurer le fournisseur de type.
Tableau 2. Expressions de requête Transact-SQL et F#
Transact-SQL (ne respecte pas la casse) | Expression de requête F# (respecte la casse) |
---|---|
Sélectionne tous les champs de la table.
|
|
Compte les enregistrements dans une table.
|
|
EXISTS
|
|
Regroupement
|
|
Regroupement avec une condition.
|
|
Regroupement avec une condition de nombre.
|
|
Regroupement, comptage et calcul de la somme.
|
|
Regroupement, comptage et tri par nombre.
|
|
IN un ensemble de valeurs spécifiées
|
|
Voir LIKE et TOP .
|
|
LIKE avec des critères spéciaux définis.
|
|
LIKE avec un modèle d’exclusion défini.
|
|
LIKE sur un champ, mais sélectionne un autre champ.
|
|
LIKE , avec recherche de sous-chaîne.
|
|
JOIN simple avec deux tables.
|
|
LEFT JOIN avec deux tables.
|
|
JOIN avec COUNT
|
|
DISTINCT
|
|
Nombre distinct.
|
|
BETWEEN
|
|
OR
|
|
OR avec tri
|
|
TOP , OR et tri.
|
|
UNION de deux requêtes.
|
|
Intersection de deux requêtes.
|
|
Condition de CASE .
|
|
Plusieurs cas.
|
|
Plusieurs tables.
|
|
Plusieurs jointures.
|
|
Plusieurs jointures externes gauches.
|
|
Le code suivant peut être utilisé afin de créer l’exemple de base de données pour ces exemples.
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);
Le code suivant contient l’exemple de code qui apparaît dans cette rubrique.
#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
type schema = SqlDataConnection<"Data Source=SERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = schema.GetDataContext()
let data = [1; 5; 7; 11; 18; 21]
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 selection in db.CourseSelection
on (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 selection in db.CourseSelection
on (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 e in db.CourseSelection
on (n.StudentID = e.StudentID)
count
}
|> printfn "%d"
printfn "\n Join with distinct."
query {
for student in db.Student do
join selection in db.CourseSelection
on (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 e in db.CourseSelection
on (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 courseSelection in db.CourseSelection
on (student.StudentID = courseSelection.StudentID) into g1
for courseSelection in g1.DefaultIfEmpty() do
leftOuterJoin course in db.Course
on (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)
Voici la sortie complète quand ce code est exécuté dans F# Interactive.
--> Referenced 'C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\3.0\Runtime\v4.0\Type Providers\FSharp.Data.TypeProviders.dll'
--> Referenced 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll'
--> Referenced 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.Linq.dll'
contains query operator
Binding session to 'C:\Users\ghogen\AppData\Local\Temp\tmp5E3C.dll'...
Binding session to 'C:\Users\ghogen\AppData\Local\Temp\tmp611A.dll'...
Is at least one student age 11? true
count query operator
Number of students: 8
last query operator.
Last number: 21
lastOrDefault query operator.
lastOrDefault: 21
exactlyOne query operator.
Student with StudentID = 1 is Abercrombie, Kim
exactlyOneOrDefault query operator.
Student with StudentID = 1 is Abercrombie, Kim
headOrDefault query operator.
head student is Abercrombie, Kim
select query operator.
StudentID, Name: 1 Abercrombie, Kim
StudentID, Name: 2 Abolrous, Hazen
StudentID, Name: 3 Hance, Jim
StudentID, Name: 4 Adams, Terry
StudentID, Name: 5 Hansen, Claus
StudentID, Name: 6 Penor, Lori
StudentID, Name: 7 Perham, Tom
StudentID, Name: 8 Peng, Yun-Feng
where query operator.
StudentID, Name: 5 Hansen, Claus
StudentID, Name: 6 Penor, Lori
StudentID, Name: 7 Perham, Tom
StudentID, Name: 8 Peng, Yun-Feng
minBy query operator.
maxBy query operator.
groupBy query operator.
Age: NULL Count at that age: 1
Age: 10 Count at that age: 1
Age: 11 Count at that age: 1
Age: 12 Count at that age: 3
Age: 13 Count at that age: 1
Age: 14 Count at that age: 1
sortBy query operator.
StudentID, Name: 1 Abercrombie, Kim
StudentID, Name: 2 Abolrous, Hazen
StudentID, Name: 4 Adams, Terry
StudentID, Name: 3 Hance, Jim
StudentID, Name: 5 Hansen, Claus
StudentID, Name: 8 Peng, Yun-Feng
StudentID, Name: 6 Penor, Lori
StudentID, Name: 7 Perham, Tom
sortByDescending query operator.
StudentID, Name: 7 Perham, Tom
StudentID, Name: 6 Penor, Lori
StudentID, Name: 8 Peng, Yun-Feng
StudentID, Name: 5 Hansen, Claus
StudentID, Name: 3 Hance, Jim
StudentID, Name: 4 Adams, Terry
StudentID, Name: 2 Abolrous, Hazen
StudentID, Name: 1 Abercrombie, Kim
thenBy query operator.
StudentID, Name: 10 Abercrombie, Kim
StudentID, Name: 11 Hansen, Claus
StudentID, Name: 12 Adams, Terry
StudentID, Name: 12 Hance, Jim
StudentID, Name: 12 Perham, Tom
StudentID, Name: 13 Penor, Lori
StudentID, Name: 14 Abolrous, Hazen
thenByDescending query operator.
StudentID, Name: 10 Abercrombie, Kim
StudentID, Name: 11 Hansen, Claus
StudentID, Name: 12 Perham, Tom
StudentID, Name: 12 Hance, Jim
StudentID, Name: 12 Adams, Terry
StudentID, Name: 13 Penor, Lori
StudentID, Name: 14 Abolrous, Hazen
groupValBy query operator.
Age: NULL Count at that age: 1
Name: Peng, Yun-Feng
Age: 10 Count at that age: 1
Name: Abercrombie, Kim
Age: 11 Count at that age: 1
Name: Hansen, Claus
Age: 12 Count at that age: 3
Name: Hance, Jim
Name: Adams, Terry
Name: Perham, Tom
Age: 13 Count at that age: 1
Name: Penor, Lori
Age: 14 Count at that age: 1
Name: Abolrous, Hazen
sumByNullable query operator
Sum of ages: 84
minByNullable
Minimum age: 10
maxByNullable
Maximum age: 14
averageBy
Average student ID: 4.500000
averageByNullable
Average age: 12
find query operator
Found a match with StudentID = 1
all query operator
Do all students have a comma in the name? true
head query operator
Found the head student with StudentID = 1
nth query operator
Third number is 11
skip query operator
StudentID = 2
StudentID = 3
StudentID = 4
StudentID = 5
StudentID = 6
StudentID = 7
StudentID = 8
skipWhile query operator
Number = 5
Number = 7
Number = 11
Number = 18
Number = 21
sumBy query operator
Sum of student IDs: 36
take query operator
StudentID = 1
StudentID = 2
takeWhile query operator
Number = 1
Number = 5
Number = 7
sortByNullable query operator
StudentID, Name, Age: 8 Peng, Yun-Feng NULL
StudentID, Name, Age: 1 Abercrombie, Kim 10
StudentID, Name, Age: 5 Hansen, Claus 11
StudentID, Name, Age: 7 Perham, Tom 12
StudentID, Name, Age: 3 Hance, Jim 12
StudentID, Name, Age: 4 Adams, Terry 12
StudentID, Name, Age: 6 Penor, Lori 13
StudentID, Name, Age: 2 Abolrous, Hazen 14
sortByNullableDescending query operator
StudentID, Name, Age: 2 Abolrous, Hazen 14
StudentID, Name, Age: 6 Penor, Lori 13
StudentID, Name, Age: 7 Perham, Tom 12
StudentID, Name, Age: 3 Hance, Jim 12
StudentID, Name, Age: 4 Adams, Terry 12
StudentID, Name, Age: 5 Hansen, Claus 11
StudentID, Name, Age: 1 Abercrombie, Kim 10
StudentID, Name, Age: 8 Peng, Yun-Feng NULL
thenByNullable query operator
StudentID, Name, Age: 1 Abercrombie, Kim 10
StudentID, Name, Age: 2 Abolrous, Hazen 14
StudentID, Name, Age: 4 Adams, Terry 12
StudentID, Name, Age: 3 Hance, Jim 12
StudentID, Name, Age: 5 Hansen, Claus 11
StudentID, Name, Age: 8 Peng, Yun-Feng NULL
StudentID, Name, Age: 6 Penor, Lori 13
StudentID, Name, Age: 7 Perham, Tom 12
thenByNullableDescending query operator
StudentID, Name, Age: 1 Abercrombie, Kim 10
StudentID, Name, Age: 2 Abolrous, Hazen 14
StudentID, Name, Age: 4 Adams, Terry 12
StudentID, Name, Age: 3 Hance, Jim 12
StudentID, Name, Age: 5 Hansen, Claus 11
StudentID, Name, Age: 8 Peng, Yun-Feng NULL
StudentID, Name, Age: 6 Penor, Lori 13
StudentID, Name, Age: 7 Perham, Tom 12
All students:
Abercrombie, Kim 1 10
Abolrous, Hazen 2 14
Hance, Jim 3 12
Adams, Terry 4 12
Hansen, Claus 5 11
Penor, Lori 6 13
Perham, Tom 7 12
Peng, Yun-Feng 8 NULL
Count of students:
Student count: 8
Exists.
"Abercrombie, Kim"
"Abolrous, Hazen"
"Hance, Jim"
"Adams, Terry"
"Hansen, Claus"
"Perham, Tom"
Group by age and count
NULL 1
10 1
11 1
12 3
13 1
14 1
Group value by age.
NULL 1
10 1
11 1
12 3
13 1
14 1
Group students by age where age > 10.
Age: 11
Hansen, Claus
Age: 12
Hance, Jim
Adams, Terry
Perham, Tom
Age: 13
Penor, Lori
Age: 14
Abolrous, Hazen
Group students by age and print counts of number of students at each age with more than 1 student.
Age: 12 Count: 3
Group students by age and sum ages.
Age: 0
Count: 1
Total years:
Age: 10
Count: 1
Total years: 10
Age: 11
Count: 1
Total years: 11
Age: 12
Count: 3
Total years: 36
Age: 13
Count: 1
Total years: 13
Age: 14
Count: 1
Total years: 14
Group students by age and count number of students at each age, and display all with count > 1 in descending order of count.
Age: 12
Count: 3
Select students from a set of IDs
Name: Abercrombie, Kim
Name: Abolrous, Hazen
Name: Hansen, Claus
Look for students with Name match _e% pattern and take first two.
Penor, Lori
Perham, Tom
Look for students with Name matching [abc]% pattern.
Abercrombie, Kim
Abolrous, Hazen
Adams, Terry
Look for students with name matching [^abc]% pattern.
Hance, Jim
Hansen, Claus
Penor, Lori
Perham, Tom
Peng, Yun-Feng
Look for students with name matching [^abc]% pattern and select ID.
3
5
6
7
8
Using Contains as a query filter.
Abercrombie, Kim
Abolrous, Hazen
Hance, Jim
Adams, Terry
Hansen, Claus
Perham, Tom
Searching for names from a list.
Join Student and CourseSelection tables.
2 Abolrous, Hazen 2
3 Hance, Jim 3
5 Hansen, Claus 5
2 Abolrous, Hazen 2
5 Hansen, Claus 5
6 Penor, Lori 6
3 Hance, Jim 3
2 Abolrous, Hazen 2
1 Abercrombie, Kim 1
2 Abolrous, Hazen 2
5 Hansen, Claus 5
2 Abolrous, Hazen 2
3 Hance, Jim 3
2 Abolrous, Hazen 2
3 Hance, Jim 3
Left Join Student and CourseSelection tables.
1 Abercrombie, Kim 10 9 3 1
2 Abolrous, Hazen 14 1 1 2
2 Abolrous, Hazen 14 4 2 2
2 Abolrous, Hazen 14 8 3 2
2 Abolrous, Hazen 14 10 4 2
2 Abolrous, Hazen 14 12 4 2
2 Abolrous, Hazen 14 14 5 2
3 Hance, Jim 12 2 1 3
3 Hance, Jim 12 7 2 3
3 Hance, Jim 12 13 5 3
3 Hance, Jim 12 15 7 3
4 Adams, Terry 12 NULL NULL NULL
5 Hansen, Claus 11 3 1 5
5 Hansen, Claus 11 5 2 5
5 Hansen, Claus 11 11 4 5
6 Penor, Lori 13 6 2 6
7 Perham, Tom 12 NULL NULL NULL
8 Peng, Yun-Feng 0 NULL NULL NULL
Join with count
15
Join with distinct.
Abercrombie, Kim 2
Abercrombie, Kim 3
Abercrombie, Kim 5
Abolrous, Hazen 2
Abolrous, Hazen 5
Abolrous, Hazen 6
Abolrous, Hazen 3
Hance, Jim 2
Hance, Jim 1
Adams, Terry 2
Adams, Terry 5
Adams, Terry 2
Hansen, Claus 3
Hansen, Claus 2
Perham, Tom 3
Join with distinct and count.
15
Selecting students with age between 10 and 15.
Abercrombie, Kim
Abolrous, Hazen
Hance, Jim
Adams, Terry
Hansen, Claus
Penor, Lori
Perham, Tom
Selecting students with age either 11 or 12.
Hance, Jim
Adams, Terry
Hansen, Claus
Perham, Tom
Selecting students in a certain age range and sorting.
Penor, Lori 13
Perham, Tom 12
Hance, Jim 12
Adams, Terry 12
Selecting students with certain ages, taking account of possibility of nulls.
Hance, Jim
Adams, Terry
Union of two queries.
Abercrombie, Kim 10
Abolrous, Hazen 14
Hance, Jim 12
Adams, Terry 12
Hansen, Claus 11
Penor, Lori 13
Perham, Tom 12
Peng, Yun-Feng NULL
Intersect of two queries.
Using if statement to alter results for special value.
1 10 10
2 14 14
3 12 12
4 12 12
5 11 11
6 13 13
7 12 12
8 NULL NULL
Using if statement to alter results special values.
1 10 10
2 14 14
3 12 12
4 12 12
5 11 11
6 13 13
7 12 12
8 NULL NULL
Multiple table select.
StudentID Name Age CourseID CourseName
1 Abercrombie, Kim 10 1 Algebra I
2 Abolrous, Hazen 14 1 Algebra I
3 Hance, Jim 12 1 Algebra I
4 Adams, Terry 12 1 Algebra I
5 Hansen, Claus 11 1 Algebra I
6 Penor, Lori 13 1 Algebra I
7 Perham, Tom 12 1 Algebra I
8 Peng, Yun-Feng NULL 1 Algebra I
1 Abercrombie, Kim 10 2 Trigonometry
2 Abolrous, Hazen 14 2 Trigonometry
3 Hance, Jim 12 2 Trigonometry
4 Adams, Terry 12 2 Trigonometry
5 Hansen, Claus 11 2 Trigonometry
6 Penor, Lori 13 2 Trigonometry
7 Perham, Tom 12 2 Trigonometry
8 Peng, Yun-Feng NULL 2 Trigonometry
1 Abercrombie, Kim 10 3 Algebra II
2 Abolrous, Hazen 14 3 Algebra II
3 Hance, Jim 12 3 Algebra II
4 Adams, Terry 12 3 Algebra II
5 Hansen, Claus 11 3 Algebra II
6 Penor, Lori 13 3 Algebra II
7 Perham, Tom 12 3 Algebra II
8 Peng, Yun-Feng NULL 3 Algebra II
1 Abercrombie, Kim 10 4 History
2 Abolrous, Hazen 14 4 History
3 Hance, Jim 12 4 History
4 Adams, Terry 12 4 History
5 Hansen, Claus 11 4 History
6 Penor, Lori 13 4 History
7 Perham, Tom 12 4 History
8 Peng, Yun-Feng NULL 4 History
1 Abercrombie, Kim 10 5 English
2 Abolrous, Hazen 14 5 English
3 Hance, Jim 12 5 English
4 Adams, Terry 12 5 English
5 Hansen, Claus 11 5 English
6 Penor, Lori 13 5 English
7 Perham, Tom 12 5 English
8 Peng, Yun-Feng NULL 5 English
1 Abercrombie, Kim 10 6 French
2 Abolrous, Hazen 14 6 French
3 Hance, Jim 12 6 French
4 Adams, Terry 12 6 French
5 Hansen, Claus 11 6 French
6 Penor, Lori 13 6 French
7 Perham, Tom 12 6 French
8 Peng, Yun-Feng NULL 6 French
1 Abercrombie, Kim 10 7 Chinese
2 Abolrous, Hazen 14 7 Chinese
3 Hance, Jim 12 7 Chinese
4 Adams, Terry 12 7 Chinese
5 Hansen, Claus 11 7 Chinese
6 Penor, Lori 13 7 Chinese
7 Perham, Tom 12 7 Chinese
8 Peng, Yun-Feng NULL 7 Chinese
Multiple Joins
Abercrombie, Kim Trigonometry
Abercrombie, Kim Algebra II
Abercrombie, Kim English
Abolrous, Hazen Trigonometry
Abolrous, Hazen English
Abolrous, Hazen French
Abolrous, Hazen Algebra II
Hance, Jim Trigonometry
Hance, Jim Algebra I
Adams, Terry Trigonometry
Adams, Terry English
Adams, Terry Trigonometry
Hansen, Claus Algebra II
Hansen, Claus Trigonometry
Perham, Tom Algebra II
Multiple Left Outer Joins
Abercrombie, Kim Trigonometry
Abercrombie, Kim Algebra II
Abercrombie, Kim English
Abolrous, Hazen Trigonometry
Abolrous, Hazen English
Abolrous, Hazen French
Abolrous, Hazen Algebra II
Hance, Jim Trigonometry
Hance, Jim Algebra I
Adams, Terry Trigonometry
Adams, Terry English
Adams, Terry Trigonometry
Hansen, Claus Algebra II
Hansen, Claus Trigonometry
Penor, Lori
Perham, Tom Algebra II
Peng, Yun-Feng
type schema
val db : schema.ServiceTypes.SimpleDataContextTypes.MyDatabase1
val student : System.Data.Linq.Table<schema.ServiceTypes.Student>
val data : int list = [1; 5; 7; 11; 18; 21]
type Nullable<'T
when 'T : (new : unit -> 'T) and 'T : struct and
'T :> System.ValueType> with
member Print : unit -> string
val num : int = 21
val student2 : schema.ServiceTypes.Student
val student3 : schema.ServiceTypes.Student
val student4 : schema.ServiceTypes.Student
val student5 : int = 1
val student6 : int = 8
val idList : int list = [1; 2; 5; 10]
val idQuery : seq<int>
val names : string [] = [|"a"; "b"; "c"|]
module Queries = begin
val query1 : System.Linq.IQueryable<string * System.Nullable<int>>
val query2 : System.Linq.IQueryable<string * System.Nullable<int>>
end
module Queries2 = begin
val query1 : System.Linq.IQueryable<string * System.Nullable<int>>
val query2 : System.Linq.IQueryable<string * System.Nullable<int>>
end