0% found this document useful (0 votes)
50 views42 pages

Language Integrated Query (LINQ)

This document discusses LINQ (Language Integrated Query) and provides examples of LINQ queries. It covers: 1. Declaring a variable to hold query results using var and inferring the type. 2. Specifying the data source using the from clause and a condition using the where clause (optional). 3. Selecting items to appear in the results using the select clause. 4. Ordering query results using the orderby clause and ascending or descending order. 5. Using aggregate operators like Count, Min, Max, Average and Sum to analyze query results.

Uploaded by

Kamran Shahid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views42 pages

Language Integrated Query (LINQ)

This document discusses LINQ (Language Integrated Query) and provides examples of LINQ queries. It covers: 1. Declaring a variable to hold query results using var and inferring the type. 2. Specifying the data source using the from clause and a condition using the where clause (optional). 3. Selecting items to appear in the results using the select clause. 4. Ordering query results using the orderby clause and ascending or descending order. 5. Using aggregate operators like Count, Min, Max, Average and Sum to analyze query results.

Uploaded by

Kamran Shahid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 42

Language Integrated Query

(LINQ)
First Program
• The LINQ query statement in this program uses the LINQ declarative
query syntax:
var queryResults =
from n in names
where n.StartsWith("S")
select n;
• The statement has four parts: the result variable declaration
beginning with var, which is assigned using a query expression
consisting of the from clause; the where clause; and the select clause
Declaring a Variable for Results Using the var
Keyword
• The LINQ query starts by declaring a variable to hold the results of the
query, which is usually done by declaring a variable with the var keyword:
• var queryResult =
• Var is a keyword in C# created to declare a general variable type that is
ideal for holding the results of LINQ queries.
• The var keyword tells the C# compiler to infer the type of the result based
on the query.
• If the query can return multiple items, then it acts like a collection of the
objects in the query data source (technically, it is not a collection; it just
looks that way).
Specifying the Data Source: from Clause
• The next part of the LINQ query is the from clause, which specifies
the data you are querying:
from n in names
• Your data source in this case is names, the array of strings declared
earlier. The variable n is just a stand-in for an individual element in
the data source, similar to the variable name following a foreach
statement.
• By specifying from, you are indicating that you are going to query a
subset of the collection, rather than iterate through all the elements.
Specify Condition: where Clause
• In the next part of the LINQ query, you specify the condition for your
query using the where clause, which looks like this:
where n.StartsWith("S")
• Any Boolean (true or false) expression that can be applied to the
items in the data source can be specified in the where clause.
• Actually, the where clause is optional and can even be omitted.
• The where clause is called a restriction operator in LINQ
• for example, a length greater than 10 (where n.Length > 10) or
containing a Q (where n.Contains("Q"))
Selecting Items: select Clause
• Finally, the select clause specifies which items appear in the result
set. The select clause looks like this:
select n
• The select clause is required because you must specify which items
from your query appear in the result set.
ORDERING QUERY RESULTS
var queryResults =
from n in names
where n.StartsWith("S")
orderby n
select n;
• By default, orderby orders in ascending order (A to Z), but you can
specify descending order (from Z to A) simply by adding the
descending keyword:
orderby n descending
ORDERING QUERY RESULTS
• to order by the last letter in the name instead of normal alphabetical
order, you just change the orderby clause to the following:
orderby n.Substring(n.Length - 1)
QUERYING A LARGE DATA SET
QUERYING A LARGE DATA SET
static void Main(string[] args) private static int[] GenerateLotsOfNumbers(int count)
{ {
int[] numbers = GenerateLotsOfNumbers(12345678); Random generator = new Random(0);
var queryResults = int[] result = new int[count];
from n in numbers for (int i = 0; i < count; i++)
where n < 1000 {
select n; result[i] = generator.Next();
Console.WriteLine("Numbers less than 1000:"); }
foreach (var item in queryResults) return result;
{Console.WriteLine(item);} }
Console.Write("Program finished, press Enter/Return
to continue:");
Console.ReadLine();
}
USING AGGREGATE OPERATORS
• if you were to change the condition to list the numbers greater than
1,000, rather than the numbers less than 1,000, there would be so
many query results that the numbers would not stop printing!
• LINQ provides a set of aggregate operators that enable you to analyze
the results of a query without having to loop through them all.
TABLE 23-1: Aggregate Operators for Numeric Results
OPERATOR DESCRIPTION
Count() Count of results
Min() Minimum value in results
Max() Maximum value in results
Average() Average value of numeric results
Sum() Total of all of numeric results
var queryResults =
from n in numbers
where n > 1000
select n
;
Console.WriteLine("Count of Numbers > 1000");
Console.WriteLine(queryResults.Count());

Console.WriteLine("Max of Numbers > 1000");


Console.WriteLine(queryResults.Max());

Console.WriteLine("Min of Numbers > 1000");


Console.WriteLine(queryResults.Min());

Console.WriteLine("Average of Numbers > 1000");


Console.WriteLine(queryResults.Average());
Console.WriteLine("Sum of Numbers > 1000");
Console.WriteLine(queryResults.Sum(n => (long) n));

There are so many large numbers in the data set that the sum of all of them
would be too large to fit into a standard 32-bit int, which is what the no-
parameter version of Sum() returns. The lambda expression enables you to
convert the result of Sum() to a long 64-bit integer, which is what you need to
hold the total of over 13 quadrillion without overflow —13,254,853,218,619,179
lambda expressions enable you to perform this kind of fix-up easily.
QUERYING COMPLEX OBJECTS
QUERYING COMPLEX OBJECTS
var queryResults =
from c in customers
where c.Region == "Asia"
select c
;
Console.WriteLine("Customers in Asia:");
foreach (Customer c in queryResults)
{
Console.WriteLine(c);
}
PROJECTION: CREATING NEW OBJECTS IN
QUERIES
• Projection is the technical term for creating a new data type from
other data types in a LINQ query.
• The select keyword is the projection operator.
• Selecting a specific field from a data object, as opposed to selecting
the entire object itself.
PROJECTION: CREATING NEW OBJECTS IN
QUERIES
• For example, to select only the City field from the Customer list in the
previous example, simply change the select clause in the query
statement to reference only the City property:
var queryResults =
from c in customers
where c.Region == "Asia"
select c.City
;
PROJECTION: CREATING NEW OBJECTS IN
QUERIES
• LINQ does not allow multiple fields in a select clause. That means the
line
select c.City, c.Country, c.Sales
• produces a compile error because the select clause takes only one
item in its parameter list.
• What you do in LINQ instead is to create a new object on-the-fly in
the select clause to hold the results you want for your query
C# anonymous-type creation
• C# anonymous-type creation syntax is used in the select clause to
create a new unnamed object type having the City, Country, and Sales
properties.
• The select clause creates the new object.
• This way, only these three properties are duplicated and carried
through the different stages of processing the query.
C# anonymous-type creation
var queryResults =
from c in customers
where c.Region == "North America"
select new { c.City, c.Country, c.Sales }
;
foreach (var item in queryResults)
{
Console.WriteLine(item);
}
USING THE SELECT DISTINCT QUERY
• Another type of query is the SELECT DISTINCT query, in which you
search for the unique values in your data — that is, values that are
not repeated. This is a fairly common need when working with
queries.
var queryResults =
customers.Select(c => c.Region).Distinct();
USING THE SELECT DISTINCT QUERY
• Because Distinct()is available only in method syntax, you make the call
to Select()using method syntax.
• However, you can call Distinct()to modify a query made in the query
syntax as well:
var queryResults =
(from c in customers select c.Region). Distinct();
USING THE ANY AND ALL METHODS
• Another type of query that you often need is for determining whether
any of your data satisfies a certain condition, or ensuring that all data
satisfies a condition.
• For example, you may need to know whether a product is out of stock
(quantity is zero), or whether a transaction has occurred.
• LINQ provides two Boolean methods — Any()and All()— that can
quickly tell you whether a condition is true or false for your data.
bool anyUSA = customers.Any(c => c.Country == "USA");
if (anyUSA)
{ Console.WriteLine("Some customers are in the USA"); }
else
{ Console.WriteLine("No customers are in the USA"); }
bool allAsia = customers.All(c => c.Region == "Asia");
if (allAsia)
{ Console.WriteLine("All customers are in Asia"); }
else
{ Console.WriteLine("Not all customers are in Asia"); }
ORDERING BY MULTIPLE LEVELS
• Now that you are dealing with objects with multiple properties, you
might be able to envision a situation where ordering the query results
by a single field is not enough.
• What if you wanted to query your customers and order the results
alphabetically by region, but then order alphabetically by country or
city name within a region.
ORDERING BY MULTIPLE LEVELS
var queryResults =
from c in customers
orderby c.Region, c.Country, c.City
select new { c.ID, c.Region, c.Country, c.City }
;

foreach (var item in queryResults)


{
Console.WriteLine(item);
}
ORDERING BY MULTIPLE LEVELS
• Add the descending keyword to any of the fields listed to reverse the
sort order for that field.
• For example, to order this query by ascending region but descending
country, simply add descending following Country in the list, like this:

orderby c.Region, c.Country descending, c.City


USING GROUP QUERIES
• A group query divides the data into groups and enables you to sort,
calculate aggregates, and compare by group.
• These are often the most interesting queries in a business context
(the ones that really drive decision-making).
• For example, you might want to compare sales by country or by
region to decide where to open another store or hire more staff.
USING GROUP QUERIES
var queryResults =
from c in customers
group c by c.Region into cg
select new { TotalSales = cg.Sum(c => c.Sales),
Region = cg.Key }
;
var orderedResults =
from cg in queryResults
orderby cg.TotalSales descending
select cg
;
USING TAKE AND SKIP
• Suppose you need to find the top five customers by sales in your data set. You
don’t know ahead of time what amount of sales qualifies a customer to be in the
top five so you can’t use a where condition to find them.
• The LINQ equivalent to this operation is the Take()method, which takes the first n
results in the query output. In practical use this needs to be combined with
orderby to get the top n results. However, the orderby is not required, as there
may be situations for which you know the data is already in the order you want,
or, for some reason, you want the first n results without caring about their order.
• The inverse of Take()is Skip(), which skips the first n results, returning the
remainder.
• Take()and Skip()are called partitioning operators in LINQ documentation because
they partition the result set into the first n results (Take()) and/or its remainder
(Skip()).
USING TAKE AND SKIP
var queryResults =
from c in customers
orderby c.Sales descending
select new { c.ID, c.City, c.Country, c.Sales }
;
USING TAKE AND SKIP
Console.WriteLine("Top Five Customers by Sales");
foreach (var item in queryResults. Take(5) )
{
Console.WriteLine(item);
}
Console.WriteLine("Customers Not In Top Five");
foreach (var item in queryResults. Skip(5) )
{
Console.WriteLine(item);
}
USING FIRST AND FIRSTORDEFAULT
• Suppose you need to find an example of a customer from Africa in
your data set. You need the actual data itself, not a true/false value or
the result set of all matching values.
• LINQ provides this capability via the First() method, which returns the
first element in a result set that matches the criteria specified.
• If there isn’t a customer from Africa, then LINQ also provides a
method to handle that contingency without additional error handling
code: FirstOrDefault().
USING FIRST AND FIRSTORDEFAULT
var queryResults = from c in customers
select new { c.City, c.Country, c.Region }
;
Console.WriteLine("A customer in Africa");
Console.WriteLine(queryResults.First(c => c.Region
== "Africa"));

Console.WriteLine("A customer in Antarctica");


Console.WriteLine(queryResults.FirstOrDefault(c =>
c.Region == "Antarctica"));
USING THE LINQ SET OPERATORS
• LINQ provides standard set operators such as Union() and Intersect()
that operate on query results.

class Order
{
public string ID { get; set; }
public decimal Amount { get; set; }
}
USING THE LINQ SET OPERATORS
List<Order> orders = new List<Order> { var customerIDs =
new Order { ID="P", Amount=100 }, from c in customers
new Order { ID="Q", Amount=200 }, select c.ID
new Order { ID="R", Amount=300 }, ;
new Order { ID="S", Amount=400 },
new Order { ID="T", Amount=500 }, var orderIDs =
new Order { ID="U", Amount=600 }, from o in orders
new Order { ID="V", Amount=700 }, select o.ID
new Order { ID="W", Amount=800 }, ;
new Order { ID="X", Amount=900 },
new Order { ID="Y", Amount=1000 },
new Order { ID="Z", Amount=1100 }
};
Intersect
var customersWithOrders =
customerIDs.Intersect(orderIDs);
Console.WriteLine("Customer IDs with Orders:");
foreach (var item in customersWithOrders)
{
Console.Write("{0} ", item);
} The Intersect() set operator finds only the
Console.WriteLine(); customer IDs that also have orders in the
orderIDsresult.
Only the IDs that appear in both result sets are
included in the intersect set.
Except
Console.WriteLine("Order IDs with no
customers:");
var ordersNoCustomers =
orderIDs.Except(customerIDs);
foreach (var item in ordersNoCustomers)
{
Console.Write("{0} ", item);
}
Console.WriteLine();
The Except() operator finds the order IDs that
have no matching customer.
Union
Console.WriteLine("All Customer and Order
IDs:");
var allCustomerOrderIDs =
orderIDs.Union(customerIDs);
foreach (var item in allCustomerOrderIDs)
{
Console.Write("{0} ", item);
}
Console.WriteLine();
The Union() operator finds the union of all the
customer ID and order ID fields.
USING JOINS
• A data set such as the customers and orders list just created, with a
shared key field (ID), enables a join query, whereby you can query
related data in both lists with a single query, joining the results
together with the key field.
USING JOINS
foreach (var item in
var queryResults = queryResults)
from c in customers {
join o in orders on c.ID equals o.ID Console.WriteLine(item);
select new }
{
c.ID,
c.City,
SalesBefore = c.Sales,
NewOrder = o.Amount,
SalesAfter = c.Sales + o.Amount
};
Reference Reading
• Chapter 23, Introduction to LINQ,
Beginning Visual C# 2012 Programming by Karli Watson, Jacob Vibe
Hammer, Jon Reid and Morgan Skinner, Wrox, 2012.

You might also like