A New Internet Library: Add Your Website/Blog or Suggest A Website/Blog to our Free Web Directory http://anil.myfunda.net.

Its very simple, free and SEO Friendly.
Submit Now....

Wednesday, February 13, 2008

SQL Bulk Copy Operations in ADO.NET 2.0

Bulk copying of data from one data source to another data source is a new feature added to ADO.NET 2.0. Bulk copy classes provides the fastest way to transfer set of data from once source to the other.

Each ADO.NET data provider provides bulk copy classes. For example, in SQL .NET data provider, the bulk copy operation is handled by SqlBulkCopy class. Data from a data source can be copied to one of the four types - DataReader, DataSet, DataTable, or XML.

Using bulk copy operation, you can transfer data between two tables on the same SQL Server, between two different SQL Servers, or even two different types of database servers.

Example:

SqlCommand cmd = new SqlCommand("DELETE FROM BulkDataTable", destination);
// Open source and destination connections.
source.Open();
destination.Open();
cmd.ExecuteNonQuery();
// Select data from Products table
cmd = new SqlCommand("SELECT * FROM Products", source);
// Execute reader
SqlDataReader reader = cmd.ExecuteReader();
// Create SqlBulkCopy
SqlBulkCopy bulkData = new SqlBulkCopy(destination);
// Set destination table name
bulkData.DestinationTableName = "BulkDataTable";
// Write data
bulkData.WriteToServer(reader);
// Close objects
bulkData.Close();
destination.Close();
source.Close();

Sending Mail From BATCH FILE

The sample script below sends an email using IIS's SMTP service running on the local machine.

Notes:
Special shell characters such as < and > must be escaped using the caret character ^
IIS requires only a minimal set of headers followed by a blank line which separates
the header from the body text. To create the blank line use the following line in
your script:
echo.>>%tempmail%
It is critical that there be no extra spaces in that line! Use exactly as shown.

The move command moves the temporary file with the mail into the pickup directory.
The pickup dir is typically c:\inetpub\mailroot\pickup but this may be different on
your system.

The account under which this script runs must have write permission to the
pickup directory. Once the file is sent the server itself deletes the file from
the pickup directory. DO NOT attempt to write the file directly to the pickup
directory. Always move it from a temp directory. IIS will attempt to send
any file in the pickup directory as soon as it detects it. Therefore you may
not have completed writing to the file before IIS tries to send and deletes the file.
Always move the file to the pickup directory.


@echo off & setlocal
:: set the temp file location
set tempmail=%temp%\tempmail.%random%.txt
:: echo the basic headers to the temp file
echo To: "Scripting Test" ^<test@paulsadowski.com^> > %tempmail%
echo From: "Me" ^<me@my.com^> >> %tempmail%
echo Subject: Test2 >> %tempmail%
:: echo the blank line that separates the header from the body text
echo.>>%tempmail%
:: echo the body text to the temp file
echo First line of body text.>> %tempmail%
echo Second line of body text.>> %tempmail%
:: move the temp file to the mail pickup directory
:: adjust this location for your system
move %tempmail% c:\inetpub\mailroot\pickup
set tempmail=
endlocal

.NET Framework NameSpaces and used Types


Complete Javascript Tutorials

Important guidelines

Printing

Other tutorials

Table of contents

Standard LINQ Query Operators

LINQ provides a wide-range of query operators, many of which have been demonstrated in the previous sections. The purpose of this section is to succinctly summarize the complete set of LINQ query operators listed in Table 1. Recall that you must import the System.Query namespace to use these operators.

Aggregate

The Aggregate operator applies a function over a sequence, with or without an initial seed value. The result can be post-processed by another function is desired.

int[] ints = { 1, 2, 3, 4, 5, 6 };

var query = from ...;


int sum = ints.Aggregate( (a, b) => a + b );

int product = ints.Aggregate( 1, (a, b) => a * b );

int sump1 = ints.Aggregate( 0, (a, b) => a + b, r => r+1 );

var result = query.Aggregate(...);


Console.WriteLine(sum); // 21

Console.WriteLine(product); // 720

Console.WriteLine(sump1); // 22

Console.WriteLine(result);


The sequence can be of any type T.

See also: Average, Count, LongCount, Max, Min, and Sum.

Table 1. List of Standard LINQ Query Operators


Operator

Lazy?

Description

Aggregate

No

Applies a function to a sequence, yielding a single value.

All

No

Applies a function to a sequence to see if all elements satisfy the function.

Any

No

Applies a function to a sequence to see if any element satisfies the function.

Average

No

Computes the average of a numeric sequence.

Cast

Yes

Yields the elements of a sequence type-casted to a given type.

Concat

Yes

Yields the concatenation of two sequences S1 and S2.

Contains

No

Searches a sequence to see if it contains a given element.

Count

No

Counts the number of elements in a sequence, yielding an integer result.

DefaultIfEmpty

Yes

Given a sequence S, yields S or a sequence with the default value if S is empty.

Distinct

Yes

Returns a sequence with duplicates eliminated.

ElementAt

No

Returns the ith element of a sequence.

ElementAtOrDefault

No

Returns the ith element of a sequence, or the default value if sequence is empty.

Empty

Yes

Yields an empty sequence.

EqualAll

No

Compares two sequences for equality.

Except

Yes

Given two sequences S1 and S2, returns the set difference S1 S2.

First

No

Returns the first element of a sequence.

FirstOrDefault

No

Returns the first element of a sequence, or the default value if sequence is empty.

Fold

No

Obsolete, see Aggregate.

GroupBy

Yes

Groups the elements of a sequence by key.

GroupJoin

Yes

Performs a join of two sequences S1 and S2, yielding a hierarchical result.

Intersect

Yes

Given two sequences S1 and S2, returns the set intersection of S1 and S2.

Join

Yes

Performs a traditional inner equijoin of two sequences S1 and S2.

Last

No

Returns the last element of a sequence.

LastOrDefault

No

Returns the last element of a sequence, or the default value if sequence is empty.

LongCount

No

Counts the number of elements in a sequence, yielding a long result.

Max

No

Returns the maximum of a sequence.

Min

No

Returns the minimum of a sequence.

OfType

Yes

Yields the elements of a sequence that match a given type.

OrderBy

Yes

Orders a sequence of elements by key into ascending order.

OrderByDescending

Yes

Orders a sequence of elements by key into descending order.

Range

Yes

Yields a sequence of integers in a given range.

Repeat

Yes

Yields a sequence of values by repeating a given value n times.

Reverse

Yes

Reverses the elements of a sequence.

Select

Yes

Applies a projection function to a sequence, yielding a new sequence.

SelectMany

Yes

Applies a projection function to flatten a sequence of sequences.

Single

No

Returns the lone element of a singleton sequence.

SingleOrDefault

No

Returns the lone element of a singleton sequence, or default if sequence is empty.

Skip

Yes

Skips the first n elements of a sequence, yielding the remaining elements.

SkipWhile

Yes

Given function F and sequence S, skips the initial elements of S where F is true.

Sum

No

Computes the sum of a numeric sequence.

Take

Yes

Yields the first n elements of a sequence.

TakeWhile

Yes

Given function F and sequence S, yields the initial elements of S where F is true.

ThenBy

Yes

Takes an ordered sequence and yields a secondary, ascending ordering.

TheyByDescending

Yes

Takes an ordered sequence and yields a secondary, descending ordering.

ToArray

No

Iterates across a sequence, capturing results in an array.

ToDictionary

No

Iterates across a sequence, capturing results in a Dictionary<K, V>.

ToList

No

Iterates across a sequence, capturing results in a List<T>.

ToLookup

No

Iterates across a sequence, capturing results in a Lookup<K, IEnumerable<V>>.

ToSequence

Yes

Casts a sequence as an IEnumerable sequence for use with standard query ops.

Union

Yes

Given two sequences S1 and S2, returns the set union of S1 and S2.

Where

Yes

Applies a Boolean function to a sequence, yielding a sub-sequence.



6.1.2. All

The All operator applies a function over a sequence, checking to see if all of the elements satisfy the function, i.e., cause the function to return true. For example, do all the doctors have pager numbers? How about all the doctors retrieved by a particular query?

Doctors doctors = new Doctors();


var query = from doc in doctors ...;


bool allHavePagers = doctors.All(doc => doc.PagerNumber > 0);

bool theseHavePagers = query.All(doc => doc.PagerNumber > 0);


See also: Any, Contains, and EqualAll.

6.1.3. Any

The Any operator applies a function over a sequence, checking to see if any of the elements satisfy the function, i.e., cause the function to return true. For example, are there any doctors living in Lake Forest?

Doctors doctors = new Doctors();


bool inLakeForest = doctors.Any(doc => doc.City == "Lake Forest");


The function is optional; if omitted, the Any operator returns true if the sequence contains at least one element.

var query = from doc in doctors

where doc.City == "Lake Forest"

select doc;


bool inLakeForest = query.Any();


See also: All, Contains, and EqualAll.

6.1.4. Average

The Average operator computes the average of a sequence of numeric values. The values are either the sequence itself, or selected out of a sequence of objects.

int[] ints = { 1, 2, 3, 4, 5, 6 };

decimal?[] values = { 1, null, 2, null, 3, 4 };

Doctors doctors = new Doctors();

var query = from ...;


double avg1 = ints.Average();

decimal? avg2 = values.Average();

double avgYears = doctors.Average( doc =>

DateTime.Now.Subtract(doc.StartDate).Days / 365.25 );

var avg = query.Average();


Console.WriteLine(avg1); // 3.5

Console.WriteLine(avg2); // 2.5

Console.WriteLine(avgYears.ToString("0.00")); // 5.72

Console.WriteLine(avg);


The values can be of type int, int?, long, long?, decimal, decimal?, double, or double?. The resulting type is double, double?, double, double?, decimal, decimal?, double, or double?, respectively.

See also: Aggregate, Count, LongCount, Max, Min, and Sum.

6.1.5. Cast

The Cast operator yields the elements of a sequence type-casted to a given type T.

System.Collections.ArrayList al = new System.Collections.ArrayList();

al.Add("abc");

al.Add("def");

al.Add("ghi");


var strings = al.Cast<string>();


foreach(string s in strings) // "abc", "def", "ghi"

Console.WriteLine(s);


The Cast operator is commonly used to wrap pre-2.0 collections (such as ArrayLists) for use with LINQ. Here's a more interesting example of searching the Windows event log for all events logged by an application:

var entries = from entry in applog.Entries.Cast<System.Diagnostics.EventLogEntry>()

where entry.Source == "ApplicationName"

orderby entry.TimeWritten descending

select entry;


See also: OfType.

6.1.6. Concat

The Concat operator concatenates two sequences S1 and S2, yielding the elements of S1 followed by the elements of S2.

int[] ints1 = { 1, 2, 3 };

int[] ints2 = { 4, 5, 6 };

var query1 = from ...;

var query2 = from ...;


var all = ints1.Concat(ints2);

var results = query1.Concat(query2);


foreach(var x in all) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);

foreach(var r in results)

Console.WriteLine(r);


The sequences may contain elements of any type T. This element type T must be the same at compile-time (e.g. object), but may differ at run-time:

object[] objects1 = { "abc", "def" };

object[] objects2 = { 1, 2, 3 };


var result = objects1.Concat(objects2);


See also: Union.

6.1.7. Contains

The Contains operator searches a sequence to see if it contains a given element. For example, is there a doctor with initials "gg" still working at University Hospital? One approach is to create a Doctor object with the initials we are looking for, and see if the collection contains this object:

Doctors doctors = new Doctors();


bool docExists = doctors.Contains( new Doctor("gg", ...) );


This assumes the Doctor class defines Equals based on a doctor's initials. Another approach (without this assumption) is to select all the initials and then see if the result contains the string "gg":

var query = from doc in doctors

select doc.Initials


bool docExists = query.Contains("gg");


See also: All, Any, EqualAll, and Where.

6.1.8. Count

The Count operator counts the number of elements in a sequence, yielding an integer result. The elements are either the sequence itself, or selected from a sequence of objects.

int[] ints = { 1, 2, 3, 4, 5, 6 };

decimal?[] values = { 1, null, 2, null, 3 };

IEnumerable<Doctor> doctors = new Doctors();

var query = from ...;


int count1 = ints.Count();

int count2 = values.Count();

int count3 = doctors.Count();

int count4 = doctors.Count( doc => doc.City == "Chicago" );

int count = query.Count();


Console.WriteLine(count1); // 6

Console.WriteLine(count2); // 5

Console.WriteLine(count3); // 12

Console.WriteLine(count4); // 5

Console.WriteLine(count);


The sequence can be of any type T.

See also: Aggregate, Average, LongCount, Max, Min, and Sum.

6.1.9. DefaultIfEmpty

Given a non-empty sequence, the DefaultIfEmpty operator yields this same sequence. If the sequence is empty, DefaultIfEmpty yields a sequence containing a single default value.

int[] ints1 = { 1, 2, 3, 4, 5, 6 };

int[] ints2 = { };

var query = from ...;


var ints = ints1.DefaultIfEmpty();

var zero = ints2.DefaultIfEmpty();

var minus1 = ints2.DefaultIfEmpty(-1);

var result = query.DefaultIfEmpty();


foreach(int x in ints) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);

foreach(int x in zero) // 0

Console.WriteLine(x);

foreach(int x in minus1) // -1

Console.WriteLine(x);

foreach(var r in result)

Console.WriteLine(r);


The sequence can be of any type T; if the sequence is empty and a default value is not provided, the default value for type T is used.

See also: FirstOrDefault, GroupJoin, LastOrDefault, SingleOrDefault, and ElementAtOrDefault.

6.1.10. Distinct

Given a sequence of elements, the Distinct operator returns the same sequence without duplicates.

int[] ints = { 1, 2, 2, 3, 2, 3, 4 };

var query = from ...;


var distinctInts = ints.Distinct();

var distinctResults = query.Distinct();


foreach(var x in distinctInts) // 1, 2, 3, 4

Console.WriteLine(x);

foreach(var r in distinctResults)

Console.WriteLine(r);


The sequence can be of any type T.

See also: Except, Intersect, and Union.

6.1.11. ElementAt

The ElementAt operator returns the ith element of a sequence; the sequence must be non-empty, and i is 0-based.

int[] ints = { 1, 2, 3, 4, 5, 6 };

Doctors doctors = new Doctors();

var query = from ...;


int third = ints.ElementAt(2);

Doctor doctor = doctors.ElementAt(2);

var result = query.ElementAt(i);


Console.WriteLine(third); // 3

Console.WriteLine(doctor.Initials); // 3rd doc in Chicago: ch

Console.WriteLine(result);


The sequence can be of any type T.

See also: ElementAtOrDefault.

6.1.12. ElementAtOrDefault

The ElementAtOrDefault operator returns the ith element of a possibly empty sequence; i is 0-based.

int[] ints1 = { 1, 2, 3, 4, 5, 6 };

int[] ints2 = { };

Doctors doctors = new Doctors();

var query = from ...;


int x1 = ints1.ElementAtOrDefault(2);

int x2 = ints1.ElementAtOrDefault(6);

int x3 = ints2.ElementAtOrDefault(0);

Doctor doc1 = doctors.ElementAtOrDefault(2);

Doctor doc2 = doctors.ElementAtOrDefault(-1);

var result = query.ElementAtOrDefault(i);


Console.WriteLine(x1); // 3

Console.WriteLine(x2); // 0

Console.WriteLine(x3); // 0

Console.WriteLine(doc1 == null); // False

Console.WriteLine(doc2 == null); // True

Console.WriteLine(result);


The sequence can be of any type T; if the sequence is empty or i is invalid, the default value for type T is returned.

See also: ElementAt.

6.1.13. Empty

The Empty operator yields an empty sequence of the given type.

var emptyDocs = System.Query.Sequence.Empty<Doctor>();


foreach(var doc in emptyDocs) // <none>

Console.WriteLine(doc);


This operator is helpful when you need an empty sequence for another operator or a method argument.

See also: Range and Repeat.

6.1.14. EqualAll

The EqualAll operator compares two sequences for equality. Two sequences are equal if they are of the same length, and contain the same sequence of elements.

var query1 = from ...;

var query2 = from ...;


bool equal = query1.EqualAll(query2);


The sequences may contain elements of any type T. This element type T must be the same at compile-time (e.g. object), but may differ at run-time:

object[] objects1 = { "abc", "def" };

object[] objects2 = { 1, 2, 3 };


bool isFalse = objects1.EqualAll(objects2); // false


The result in such cases is false.

See also: All, Any, and Contains.

6.1.15. Except

Given two sequences of elements S1 and S2, the Except operator returns the distinct elements of S1 not in S2. In other words, Except computes the set difference S1 S2.

int[] intsS1 = { 1, 2, 2, 3, 2, 3, 4, 5, 6 };

int[] intsS2 = { 1, 3, 6, 7 };

var query1 = from ...;

var query2 = from ...;


var diffInts = intsS1.Except(intsS2);

var diffResults = query1.Except(query2);


foreach(var x in diffInts) // 2, 4, 5

Console.WriteLine(x);

foreach(var r in diffResults)

Console.WriteLine(r);


The sequences may contain elements of any type T. This element type T must be the same at compile-time (e.g. object), but may differ at run-time:

object[] objects1 = { "abc", "def" };

object[] objects2 = { 1, 2, 3 };


var result = objects1.Except(objects2);


See also: Distinct, Intersect, and Union.

6.1.16. First

The First operator returns the first element of a sequence; the sequence must be non-empty.

int[] ints = { 1, 2, 3, 4, 5, 6 };

Doctors doctors = new Doctors();

var query = from ...;


int first = ints.First();

Doctor doctor = doctors.First(doc => doc.City == "Chicago");

var result = query.First();


Console.WriteLine(first); // 1

Console.WriteLine(doctor.Initials); // mbl

Console.WriteLine(result);


The sequence can be of any type T.

See also: FirstOrDefault.

6.1.17. FirstOrDefault

The FirstOrDefault operator returns the first element of a possibly empty sequence.

int[] ints1 = { 1, 2, 3, 4, 5, 6 };

int[] ints2 = { };

Doctors doctors = new Doctors();

var query = from ...;


int x1 = ints1.FirstOrDefault();

int x2 = ints2.FirstOrDefault();

Doctor doc1 = doctors.FirstOrDefault(doc => doc.City == "Chicago");

Doctor doc2 = doctors.FirstOrDefault(doc => doc.City == "Planet Mars");

var result = query.FirstOrDefault();


Console.WriteLine(x1); // 1

Console.WriteLine(x2); // 0

Console.WriteLine(doc1 == null); // False

Console.WriteLine(doc2 == null); // True

Console.WriteLine(result);


The sequence can be of any type T; if the sequence is empty, the default value for type T is returned.

See also: First.

6.1.18. Fold

The Fold operator is considered obsolete, see Aggregate.

6.1.19. GroupBy

The GroupBy operator groups the elements of a sequence by key; the keys are yielded by a function applied to each element. Each resulting group is an IEnumerable sequence of elements S with a key K.

Doctors doctors = new Doctors();


var groups = doctors.GroupBy(doc => doc.City);


foreach(var group in groups)

{

Console.WriteLine("{0}:", group.Key); // Chicago, Evanston, ...

foreach(var doc in group) // {mbl,jl,...}, {ch,cm,...}, ...

Console.WriteLine(" {0}", doc.Initials);

}


A second version allows you to project exactly what data to store in the group, such as only the doctor's initials:

Doctors doctors = new Doctors();


var groups2 = doctors.GroupBy(doc => doc.City, doc => doc.Initials);


foreach(var group in groups2)

{

Console.WriteLine("{0}:", group.Key); // Chicago, Evanston, ...

foreach(var initials in group) // {mbl,jl,...}, {ch,cm,...}, ...

Console.WriteLine(" {0}", initials);

}


Additional versions allow you to provide a comparer of type IEqualityComparer for comparing keys.

Use of the group by clause in a query expression translates into application of the GroupBy operator. For example, the following statements are equivalent:

var groups = doctors.GroupBy(doc => doc.City);

var groups = from doc in doctors

group doc by doc.City into g

select g;


var groups2 = doctors.GroupBy(doc => doc.City, doc => doc.Initials);

var groups2 = from doc in doctors

group doc.Initials by doc.City into g

select g;


See also: OrderBy.

6.1.20. GroupJoin

The GroupJoin operator performs a join of two sequences S1 and S2, based on the keys selected from S1's and S2's elements. The keys are yielded by functions applied to each element; a third function determines the data projected by the join.

Unlike an inner join which yields essentially a table of joined records, the result of a GroupJoin is hierarchical. For each element in S1, there's a possibly empty sub-sequence of matching elements from S2. For example, the following query joins Doctors and Calls via the doctors' initials to determine which doctors are working on what dates:

DataSets.SchedulingDocs ds = FillDataSet();


var working = ds.Doctors.GroupJoin( ds.Calls,

doc => doc.Initials,

call => call.Initials,

(doc,call) => new { doc.Initials, Calls=call }

);


foreach(var record in working)

{

Console.WriteLine("{0}:", record.Initials);

foreach(var call in record.Calls)

Console.WriteLine(" {0}", call.DateOfCall);

}


Here's the output:

ay:

11/2/2006 12:00:00 AM

bb:

ch:

cm:

jl:

10/2/2006 12:00:00 AM

11/1/2006 12:00:00 AM

.

.

.


Use of the join into clause in a query expression translates into application of the GroupJoin operator. For example, the following statements are equivalent:

var working = ds.Doctors.GroupJoin( ds.Calls,

doc => doc.Initials,

call => call.Initials,

(doc,call) => new { doc.Initials, Calls=call }

);


var working = from doc in ds.Doctors

join call in ds.Calls

on doc.Initials equals call.Initials

into j

select new { doc.Initials, Calls = j };


To perform a traditional left outer join (and thus flatten the result into a table), use the DefaultIfEmpty operator as follows:

var working = from doc in ds.Doctors

join call in ds.Calls

on doc.Initials equals call.Initials

into j

from r in j.DefaultIfEmpty()

select new { doc.Initials, Call = r };


foreach(var record in working)

Console.WriteLine("{0}: {1}",

record.Initials,

(record.Call == null) ? "" : record.Call.DateOfCall.ToString());


See also: Join.

6.1.21. Intersect

Given two sequences of elements S1 and S2, the Intersect operator returns the distinct elements of S1 that also appear in S2. In other words, Intersect computes the set intersection of S1 and S2.

int[] intsS1 = { 1, 2, 2, 3, 2, 3, 4, 5, 6, 8 };

int[] intsS2 = { 6, 1, 3, 6, 7 };

var query1 = from ...;

var query2 = from ...;


var commonInts = intsS1.Intersect(intsS2);

var commonResults = query1.Intersect(query2);


foreach(var x in commonInts) // 1, 3, 6

Console.WriteLine(x);

foreach(var r in commonResults)

Console.WriteLine(r);


The sequences may contain elements of any type T. This element type T must be the same at compile-time (e.g. object), but may differ at run-time:

object[] objects1 = { "abc", "def" };

object[] objects2 = { 1, 2, 3 };


var result = objects1.Intersect(objects2);


See also: Distinct, Except, and Union.

6.1.22. Join

The Join operator performs an inner equijoin of two sequences S1 and S2, based on the keys selected from S1's and S2's elements. The keys are yielded by functions applied to each element; a third function determines the data projected by the join. For example, the following query joins Doctors and Calls via the doctors' initials to determine which doctors are working on what dates:

DataSets.SchedulingDocs ds = FillDataSet();


var working = ds.Doctors.Join( ds.Calls,

doc => doc.Initials,

call => call.Initials,

(doc,call) => new { doc.Initials, call.DateOfCall }

);


foreach(var record in working)

Console.WriteLine(record);


The query yields pairs of the form (Initials, DateOfCall), created from the joined Doctor and Call elements. Here's the output:

{Initials=ay, DateOfCall=11/2/2006 12:00:00 AM}

{Initials=jl, DateOfCall=10/2/2006 12:00:00 AM}

{Initials=jl, DateOfCall=11/1/2006 12:00:00 AM}

.

.

.


Use of the join clause in a query expression translates into application of the Join operator. For example, the following statements are equivalent:

var working = ds.Doctors.Join( ds.Calls,

doc => doc.Initials,

call => call.Initials,

(doc,call) => new { doc.Initials, call.DateOfCall }

);


var working = from doc in ds.Doctors

join call in ds.Calls

on doc.Initials equals call.Initials

select new { doc.Initials, call.DateOfCall };


See also: GroupJoin.

6.1.23. Last

The Last operator returns the last element of a sequence; the sequence must be non-empty.

int[] ints = { 1, 2, 3, 4, 5, 6 };

Doctors doctors = new Doctors();

var query = from ...;


int last = ints.Last();

Doctor doctor = doctors.Last(doc => doc.City == "Chicago");

var result = query.Last();


Console.WriteLine(last); // 6

Console.WriteLine(doctor.Initials); // tm

Console.WriteLine(result);


The sequence can be of any type T.

See also: LastOrDefault.

6.1.24. LastOrDefault

The LastOrDefault operator returns the last element of a possibly empty sequence.

int[] ints1 = { 1, 2, 3, 4, 5, 6 };

int[] ints2 = { };

Doctors doctors = new Doctors();

var query = from ...;


int x1 = ints1.LastOrDefault();

int x2 = ints2.LastOrDefault();

Doctor doc1 = doctors.LastOrDefault(doc => doc.City == "Chicago");

Doctor doc2 = doctors.LastOrDefault(doc => doc.City == "Planet Mars");

var result = query.LastOrDefault();


Console.WriteLine(x1); // 6

Console.WriteLine(x2); // 0

Console.WriteLine(doc1 == null); // False

Console.WriteLine(doc2 == null); // True

Console.WriteLine(result);


The sequence can be of any type T; if the sequence is empty, the default value for type T is returned.

See also: Last.

6.1.25. LongCount

The LongCount operator counts the number of elements in a sequence, yielding a long result. The elements are either the sequence itself, or selected from a sequence of objects.

int[] ints = { 1, 2, 3, 4, 5, 6 };

decimal?[] values = { 1, null, 2, null, 3 };

IEnumerable<Doctor> doctors = new Doctors();

var query = from ...;


long count1 = ints.LongCount();

long count2 = values.LongCount();

long count3 = doctors.LongCount();

long count4 = doctors.LongCount( doc => doc.City == "Chicago" );

long count = query.LongCount();


Console.WriteLine(count1); // 6

Console.WriteLine(count2); // 5

Console.WriteLine(count3); // 12

Console.WriteLine(count4); // 5

Console.WriteLine(count);


The sequence can be of any type T.

See also: Aggregate, Average, Count, Max, Min, and Sum.

6.1.26. Max

The Max operator finds the maximum of a sequence of values. The values are either the sequence itself, or selected out of a sequence of objects, and must implement IComparable for comparison purposes.

int[] ints = { 1, 2, 3, 6, 5, 4 };

decimal?[] values = { 1, null, 4, null, 3, 2 };

Doctors doctors = new Doctors();

var query = from ...;


int max1 = ints.Max();

decimal? max2 = values.Max();

string maxInitials = doctors.Max( doc => doc.Initials );

double maxYears = doctors.Max( doc =>

DateTime.Now.Subtract(doc.StartDate).Days / 365.25 );

var max = query.Max();


Console.WriteLine(max1); // 6

Console.WriteLine(max2); // 4

Console.WriteLine(maxInitials); // "vj"

Console.WriteLine(maxYears.ToString("0.00")); // 11.43

Console.WriteLine(max);


The sequence can be of any type T; the resulting type is the same.

See also: Aggregate, Average, Count, LongCount, Min, and Sum.

6.1.27. Min

The Min operator finds the minimum of a sequence of values. The values are either the sequence itself, or selected out of a sequence of objects, and must implement IComparable for comparison purposes.

int[] ints = { 6, 2, 3, 1, 5, 4 };

decimal?[] values = { 4, null, 1, null, 3, 2 };

Doctors doctors = new Doctors();

var query = from ...;


int min1 = ints.Min();

decimal? min2 = values.Min();

string minInitials = doctors.Min( doc => doc.Initials );

double minYears = doctors.Min( doc =>

DateTime.Now.Subtract(doc.StartDate).Days / 365.25 );

var min = query.Min();


Console.WriteLine(min1); // 1

Console.WriteLine(min2); // 1

Console.WriteLine(minInitials); // "ay"

Console.WriteLine(minYears.ToString("0.00")); // 0.67

Console.WriteLine(min);


The sequence can be of any type T; the resulting type is the same.

See also: Aggregate, Average, Count, LongCount, Max, and Sum.

6.1.28. OfType

The OfType operator yields the elements of a sequence that match a given type T. In other words, OfType filters a sequence by type.

System.Collections.ArrayList al = new System.Collections.ArrayList();

al.Add(1);

al.Add("abc");

al.Add(2);

al.Add("def");

al.Add(3);


var strings = al.OfType<string>();


foreach(string s in strings) // "abc", "def"

Console.WriteLine(s);


The OfType operator is commonly used to (a) wrap pre-2.0 collections (such as ArrayLists) for use with LINQ and (b) filter mixed collections. Here's a more interesting example of searching a user's Outlook contacts with LINQ:

Outlook.MAPIFolder folder = this.ActiveExplorer().Session.

GetDefaultFolder( Outlook.OlDefaultFolders.olFolderContacts );


var contacts = from contact in folder.Items.OfType<Outlook.ContactItem>()

where .

. // search criteria, e.g. contact.Email1Address != null

.

select contact;


See also: Cast.

6.1.29. OrderBy

The OrderBy operator orders a sequence of elements into ascending order; the keys used to order the sequence are yielded by a function applied to each element.

int[] ints = {3, 1, 6, 4, 2, 5};

Doctors doctors = new Doctors();


var sorted = ints.OrderBy(x => x);

var docs = doctors.OrderBy(doc => doc.Initials);


foreach(var x in sorted) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);

foreach(var doc in docs) // ay, bb, ..., vj

Console.WriteLine(doc.Initials);


A second version allows you to provide a comparer of type IComparer for comparing keys and thus controlling the ordering, e.g., when you want to compare strings in a case-insensitive manner:

var docs = doctors.OrderBy(doc => doc.Initials,

StringComparer.CurrentCultureIgnoreCase);


Use of the orderby clause in a query expression translates into application of the OrderBy operator. For example, the following statements are equivalent:

var docs = doctors.OrderBy(doc => doc.Initials);


var docs = from doc in doctors

orderby doc.Initials

select doc;


See also: OrderByDescending, ThenBy, and ThenByDescending.

6.1.30. OrderByDescending

The OrderByDescending operator orders a sequence of elements into descending order; the keys used to order the sequence are yielded by a function applied to each element.

int[] ints = {3, 1, 6, 4, 2, 5};

Doctors doctors = new Doctors();


var sorted = ints.OrderByDescending(x => x);

var docs = doctors.OrderByDescending(doc => doc.Initials);


foreach(var x in sorted) // 6, 5, 4, 3, 2, 1

Console.WriteLine(x);

foreach(var doc in docs) // vj, tm, ..., ay

Console.WriteLine(doc.Initials);


A second version allows you to provide a comparer of type IComparer for comparing keys and thus controlling the ordering, e.g., when you want to compare strings in a case-insensitive manner:

var docs = doctors.OrderByDescending(doc => doc.Initials,

StringComparer.CurrentCultureIgnoreCase);


Use of the orderby clause in a query expression with the descending keyword translates into application of the OrderByDescending operator. For example, the following statements are equivalent:

var docs = doctors.OrderByDescending(doc => doc.Initials);


var docs = from doc in doctors

orderby doc.Initials descending

select doc;


See also: OrderBy, ThenBy, and ThenByDescending.

6.1.31. Range

The Range operator yields a sequence of integers in the given range, inclusive.

var oneToTen = System.Query.Sequence.Range(1, 10);


foreach(var x in oneToTen) // 1, 2, 3, ..., 10

Console.WriteLine(x);


See also: Empty and Repeat.

6.1.32. Repeat

The Repeat operator yields a sequence of values by repeating a given value n times.

var zeros = System.Query.Sequence.Repeat(0, 8);

var strings = System.Query.Sequence.Repeat("", n);


Console.WriteLine(zeros.Count()); // 8

Console.WriteLine(strings.Count()); // n


foreach(var zero in zeros) // 0, 0, ..., 0

Console.WriteLine(zero);


See also: Empty and Range.

6.1.33. Reverse

The Reverse operator reverses the elements of a sequence.

int[] ints = {1, 2, 3, 4, 5, 6};

Doctors doctors = new Doctors();


var revInts = ints.Reverse();

var docs = from doc in doctors

orderby doc.Initials

select doc;

var revDocs = docs.Reverse();


foreach(var x in revInts) // 6, 5, 4, 3, 2, 1

Console.WriteLine(x);

foreach(var doc in revDocs) // vj, tm, ..., ay

Console.WriteLine(doc.Initials);


See also: OrderBy and OrderByDescending.

6.1.34. Select

The Select operator applies a projection function over a sequence of elements, yielding a sequence of possibly new elements.

int[] ints = {1, 2, 3, 4, 5, 6};

Doctors doctors = new Doctors();


var sameInts = ints.Select(x => x);

var chicago = doctors.Where(d => d.City == "Chicago").Select(d => d.Initials);

var names = doctors.Select(d => new {LN=d.FamilyLastName, FN=d.GivenFirstName});


foreach(var x in sameInts) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);

foreach(var d in chicago) // mbl, jl, kl, py, tm

Console.WriteLine(d);

foreach(var n in names) // {LN=Larsen, FN=Marybeth}, ...

Console.WriteLine(n);


Use of the select clause in a query expression translates into application of the Select operator (except in trivial cases where the Select operator can be optimized away). For example, the following statements are equivalent:

var chicago = doctors.Where(d => d.City == "Chicago").Select(d => d.Initials);


var chicago = from d in doctors

where d.City == "Chicago"

select d.Initials;


A second version of the Select operator provides an element's 0-based index in the sequence along with the element itself, for example:

var sumLast3 = ints.Select( (x,index) => (index >= ints.Length-3) ? x : 0 ).Sum();


Console.WriteLine(sumLast3); // 15


See also: SelectMany and Where.

6.1.35. SelectMany

The SelectMany operator applies a projection function over a sequence of sequences, yielding a "flattened" sequence of possibly new elements. For example, turning an array of arrays into an array:

List<int[]> list = new List<int[]>();

int[] ints123 = {1, 2, 3};

int[] ints456 = {4, 5, 6};


list.Add(ints123);

list.Add(ints456);


var flat = list.SelectMany(x => x);


foreach (var x in list) // Int32[], Int32[]

Console.WriteLine(x);

foreach (var x in flat) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);


The SelectMany operator is commonly used to flatten hierarchical data. For example, the following query yields the list of doctors working in October 2006, with sub-lists of the calls each is working:

DataSets.SchedulingDocs ds = FillDataSet();


var oct2006 = from d in ds.Doctors

join c in ds.Calls

on d.Initials equals c.Initials

where c.DateOfCall >= new DateTime(2006, 10, 1) &&

c.DateOfCall <= new DateTime(2006, 10, 31)

group c by d.Initials into g

select g;


foreach (var group in oct2006) // jl: 1, mbl: 2

{

Console.WriteLine("{0}: {1}", group.Key, group.Count());

foreach (var call in group)

Console.WriteLine(call.DateOfCall);

}


To flatten the hierarchy into just the list of calls:

var calls = oct2006.SelectMany(call => call);


foreach (var c in calls)

Console.WriteLine(c.DateOfCall);


Use of the select clause in a query expression on all but the initial from clause translates into application of the SelectMany operator. For example, here's another way to flatten the list of calls for doctors working in October 2006:

var calls = from d in ds.Doctors

from c in ds.Calls

where

d.Initials == c.Initials &&

c.DateOfCall >= new DateTime(2006, 10, 1) &&

c.DateOfCall <= new DateTime(2006, 10, 31)

select c;


This is translated into the following application of the SelectMany operator:

var calls = ds.Doctors.SelectMany(

d => ds.Calls.Where(c => d.Initials == c.Initials &&

c.DateOfCall >= new DateTime(2006, 10, 1) &&

c.DateOfCall <= new DateTime(2006, 10, 31)));


A second version of the SelectMany operator provides an element's 0-based index in the outer sequence along with the element itself.

See also: Select and Where.

6.1.36. Single

The Single operator returns the lone element of a sequence; the sequence must contain exactly one element.

int[] ints = { 3 };

Doctors doctors = new Doctors();

var query = from ...;


int lone = ints.Single();

Doctor doctor = doctors.Single(doc => doc.Initials == "mbl");

var result = query.Single();


Console.WriteLine(lone); // 3

Console.WriteLine(doctor.PagerNumber); // 52248

Console.WriteLine(result);


The sequence can be of any type T.

See also: SingleOrDefault.

6.1.37. SingleOrDefault

The SingleOrDefault operator returns the lone element of a sequence; the sequence must be empty or contain exactly one element.

int[] ints1 = { 3 };

int[] ints2 = { };

Doctors doctors = new Doctors();

var query = from ...;


int x1 = ints1.SingleOrDefault();

int x2 = ints2.SingleOrDefault();

Doctor doc1 = doctors.SingleOrDefault(doc => doc.Initials == "mbl");

Doctor doc2 = doctors.SingleOrDefault(doc => doc.Initials == "AAA");

var result = query.SingleOrDefault();


Console.WriteLine(x1); // 3

Console.WriteLine(x2); // 0

Console.WriteLine(doc1 == null); // False

Console.WriteLine(doc2 == null); // True

Console.WriteLine(result);


The sequence can be of any type T; if the sequence is empty, the default value for type T is returned.

See also: Single.

6.1.38. Skip

The Skip operator skips the first n elements of a sequence, yielding the remaining elements. If n <= 0 the result is the sequence itself; if n >= sequence's length the result is an empty sequence.

int[] ints = { 1, 2, 3, 4, 5, 6 };

var query = from ...;


var last3 = ints.Skip(3);

var bottom10 = query.Skip( query.Count() - 10 );


foreach(var x in last3) // 4, 5, 6

Console.WriteLine(x);

foreach(var r in bottom10)

Console.WriteLine(r);


The sequence can be of any type T.

See also: Take.

6.1.39. SkipWhile

Given a function F and a sequence S, the SkipWhile operator skips the first n elements of S where F returns true, yielding the remaining elements. Two versions of F are supported: accepting an element, or accepting an element along with its 0-based index in the sequence.

int[] ints = { 1, 2, 3, 4, 5, 6 };

var query = from ...;


var all = ints.SkipWhile(x => false);

var none = ints.SkipWhile(x => true);

var last3 = ints.SkipWhile( (x,i) => i < 3 );

var lastN = query.SkipWhile(result => ...);


foreach(var x in all) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);

foreach(var x in none) // <none>

Console.WriteLine(x);

foreach(var x in last3) // 4, 5, 6

Console.WriteLine(x);

foreach(var r in lastN)

Console.WriteLine(r);


The sequence can be of any type T.

See also: TakeWhile and Where.

6.1.40. Sum

The Sum operator computes the sum of a sequence of numeric values. The values are either the sequence itself or selected out of a sequence of objects.

int[] ints = { 1, 2, 3, 4, 5, 6 };

decimal?[] values = { 1, null, 2, null, 3, 4 };

Doctors doctors = new Doctors();

var query = from ...;


int sum1 = ints.Sum();

decimal? sum2 = values.Sum();

double sumYears = doctors.Sum( doc =>

DateTime.Now.Subtract(doc.StartDate).Days / 365.25 );

var sum = query.Sum();


Console.WriteLine(sum1); // 21

Console.WriteLine(sum2); // 10

Console.WriteLine(sumYears.ToString("0.00")); // 68.61

Console.WriteLine(sum);


The values can be of type int, int?, long, long?, decimal, decimal?, double, or double?. The resulting type is the same.

See also: Aggregate, Average, Count, LongCount, Max, and Min.

6.1.41. Take

The Take operator yields the first n elements of a sequence. If n <= 0 the result is an empty sequence; if n >= sequence's length the result is the sequence itself.

int[] ints = { 1, 2, 3, 4, 5, 6 };

var query = from ...;


var first3 = ints.Take(3);

var top10 = query.Take(10);


foreach(var x in first3) // 1, 2, 3

Console.WriteLine(x);

foreach(var r in top10)

Console.WriteLine(r);


The sequence can be of any type T.

See also: Skip.

6.1.42. TakeWhile

Given a function F and a sequence S, the TakeWhile operator yields the first n elements of S where F returns true. Two versions of F are supported: accepting an element, or accepting an element along with its 0-based index in the sequence.

int[] ints = { 1, 2, 3, 4, 5, 6 };

var query = from ...;


var all = ints.TakeWhile(x => true);

var none = ints.TakeWhile(x => false);

var first3 = ints.TakeWhile( (x,i) => i < 3 );

var firstN = query.TakeWhile(result => ...);


foreach(var x in all) // 1, 2, 3, 4, 5, 6

Console.WriteLine(x);

foreach(var x in none) // <none>

Console.WriteLine(x);

foreach(var x in first3) // 1, 2, 3

Console.WriteLine(x);

foreach(var r in firstN)

Console.WriteLine(r);


The sequence can be of any type T.

See also: SkipWhile and Where.

6.1.43. ThenBy

The ThenBy operator takes an ordered sequence and yields a secondary, ascending ordering; the keys used for the secondary ordering are yielded by a function applied to each element. Ordered sequences are typically produced by OrderBy or OrderByDescending, but can also be produced by ThenBy and ThenByDescending to yield additional sub-orderings.

Doctors doctors = new Doctors();


var docs = doctors.OrderBy(doc => doc.City).ThenBy(doc => doc.Initials);


foreach(var doc in docs)

Console.WriteLine("{0}: {1}", doc.City, doc.Initials);


A second version allows you to provide a comparer of type IComparer for comparing keys and thus controlling the ordering, e.g., when you want to compare strings in a case-insensitive manner:

var docs = doctors.OrderBy(doc => doc.City)

.ThenBy(doc => doc.Initials,

StringComparer.CurrentCultureIgnoreCase);


Use of an orderby clause in a query expression with subsequent keys translates into application of the ThenBy operator. For example, the following are equivalent:

var docs = doctors.OrderBy(doc => doc.City).ThenBy(doc => doc.Initials);


var docs = from doc in doctors

orderby doc.City, doc.Initials

select doc;


See also: OrderBy, OrderByDescending, and ThenByDescending.

6.1.44. ThenByDescending

The ThenByDescending operator takes an ordered sequence and yields a secondary, descending ordering; the keys used for the secondary ordering are yielded by a function applied to each element. Ordered sequences are typically produced by OrderBy or OrderByDescending, but can also be produced by ThenBy and ThenByDescending to yield additional sub-orderings.

Doctors doctors = new Doctors();


var docs = doctors.OrderBy(doc => doc.City).ThenByDescending(doc => doc.Initials);


foreach(var doc in docs)

Console.WriteLine("{0}: {1}", doc.City, doc.Initials);


A second version allows you to provide a comparer of type IComparer for comparing keys and thus controlling the ordering, e.g., when you want to compare strings in a case-insensitive manner:

var docs = doctors.OrderBy(doc => doc.City)

.ThenByDescending(doc => doc.Initials,

StringComparer.CurrentCultureIgnoreCase);


Use of an orderby clause in a query expression with subsequent keys and the descending keyword translates into application of the ThenBy operator. For example, the following are equivalent:

var docs = doctors.OrderBy(doc => doc.City).ThenByDescending(doc => doc.Initials);


var docs = from doc in doctors

orderby doc.City, doc.Initials descending

select doc;


See also: OrderBy, OrderByDescending, and ThenBy.

6.1.45. ToArray

The ToArray operator iterates across a sequence of values, yielding an array containing these values. For example, doctors living in Chicago:

Doctors doctors = new Doctors();


var query = from doc in doctors

where doc.City == "Chicago"

select doc;


Doctor[] chicago = query.ToArray();


Since queries are lazily evaluated, ToArray is commonly used to execute a query and capture the results in a simple data structure.

See also: ToDictionary, ToList, ToLookup, and ToSequence.

6.1.46. ToDictionary

The ToDictionary operator iterates across a sequence of values, yielding a Dictionary<K, V> of (key, value) pairs. Each key must be unique, resulting in a one-to-one mapping of key to value. For example, storing doctors by their initials:

Doctors doctors = new Doctors();


var query = from doc in doctors

where doc.City == "Chicago"

select doc;


Dictionary<string, Doctor> chicago = query.ToDictionary(doc => doc.Initials);


foreach(var pair in chicago)

Console.WriteLine("{0}: {1}", pair.Key, pair.Value.PagerNumber);


Since queries are lazily evaluated, ToDictionary is commonly used to execute a query and capture the results in a data structure that supports efficient lookup by key. For example, finding a doctor via their initials:

Doctor mbl = chicago["mbl"];


Another version provides control over exactly what values are stored in the data structure, e.g., only the doctor's email address:

Dictionary<string, string> emails = doctors.ToDictionary(doc => doc.Initials,

doc => doc.EmailAddress);


Finally, additional versions of ToDictionary allow you to provide a comparer of type IEqualityComparer for comparing keys.

See also: ToArray, ToList, ToLookup, and ToSequence.

6.1.47. ToList

The ToList operator iterates across a sequence of values, yielding a List<T> containing these values. For example, doctors living in Chicago:

Doctors doctors = new Doctors();


var query = from doc in doctors

where doc.City == "Chicago"

select doc;


List<Doctor> chicago = query.ToList();


Since queries are lazily evaluated, ToList is commonly used to execute a query and capture the results in a flexible data structure.

See also: ToArray, ToDictionary, ToLookup, and ToSequence.

6.1.48. ToLookup

The ToLookup operator iterates across a sequence of values, yielding a Lookup<K, V> of (key, value) pairs. The keys do not need to be unique; values with the same key form a collection under that key, resulting in a one-to-many mapping of key to values. For example, grouping doctors by city:

Doctors doctors = new Doctors();


var query = from doc in doctors

select doc;


Lookup<string, Doctor> cities = query.ToLookup(doc => doc.City);


foreach(var pair in cities)

{

Console.WriteLine("{0}:", pair.Key); // city

foreach(var doc in pair) // doctors in that city

Console.WriteLine(" {0}", doc.Initials);

}


Since queries are lazily evaluated, ToLookup is commonly used to execute a query and capture the results in a data structure that supports efficient lookup by key. For example, finding the doctors living in Chicago:

IEnumerable<Doctor> docs = cities["Chicago"];


Another version provides control over exactly what values are stored in the data structure, e.g., only the doctor's initials:

Lookup<string, string> cities = doctors.ToLookup(doc => doc.City,

doc => doc.Initials);


Finally, additional versions of ToLookup allow you to provide a comparer of type IEqualityComparer for comparing keys.

See also: ToArray, ToDictionary, ToList, and ToSequence.

6.1.49. ToSequence

The ToSequence operator casts a sequence as a sequence, thereby hiding any public members of the original sequencein particular those that might conflict or compete with the standard query operators. Use this operator when you want to gain access to the standard LINQ query operators.

For example, the following use of the Count query operator fails to compile:

Doctors doctors = new Doctors();

int count = doctors.Count(doc => doc.City == "Chicago"); // ERROR!


It fails because the Doctors class provides a conflicting Count property (inherited from List<T>). The ToSequence operator provides a quick solution:

int count1 = doctors.Count;

int count2 = doctors.ToSequence().Count();

int count3 = doctors.ToSequence().Count( doc => doc.City == "Chicago" );


Console.WriteLine(count1); // 12

Console.WriteLine(count2); // 12

Console.WriteLine(count3); // 5


See also: ToArray, ToDictionary, ToList, and ToLookup.

6.1.50. Union

Given two sequences of elements S1 and S2, the Union operator returns the distinct elements of S1, followed by the distinct elements of S2 not in S1. In other words, Union computes the set union of S1 and S2.

int[] intsS1 = { 1, 2, 2, 3, 2, 3, 4, 6 };

int[] intsS2 = { 6, 1, 3, 5 };

var query1 = from ...;

var query2 = from ...;


var allInts = intsS1.Union(intsS2);

var allResults = query1.Union(query2);


foreach(var x in allInts) // 1, 2, 3, 4, 6, 5

Console.WriteLine(x);

foreach(var r in allResults)

Console.WriteLine(r);


The sequences may contain elements of any type T. This element type T must be the same at compile-time (e.g. object), but may differ at run-time:

object[] objects1 = { "abc", "def" };

object[] objects2 = { 1, 2, 3 };


var result = objects1.Union(objects2);


See also: Distinct, Except, and Intersect.

6.1.51. Where

The Where operator applies a function to a sequence of elements, yielding a sub-sequence of these elements.

int[] ints = {1, 2, 3, 4, 5, 6};

Doctors doctors = new Doctors();


var even = ints.Where( x => x % 2 == 0);

var chicago = doctors.Where( doc => doc.City == "Chicago" );


foreach(var x in even) // 2, 4, 6

Console.WriteLine(x);

foreach(var doc in chicago) // mbl, jl, kl, py, tm

Console.WriteLine(doc.Initials);


Use of the where clause in a query expression translates into application of the Where operator. For example, the following statements are equivalent:

var chicago = doctors.Where( doc => doc.City == "Chicago" );


var chicago = from doc in doctors

where doc.City == "Chicago"

select doc;


A second version of the Where operator provides an element's 0-based index in the sequence along with the element itself, for example:

var last3 = ints.Where( (x,index) => (index >= ints.Length-3) ? true : false );


foreach (var x in last3) // 4, 5, 6

Console.WriteLine(x);


See also: Select.

Dotnet-Interviews