Table of contents
Problems I'm having :
_List = (from hero in _List orderby HaveColor(hero) descending select hero).ToList<int>();
Basic LINQ query operations
get data source
In a LINQ query, the first step is to specify the data source. Like most programming languages, when using C#, a variable must be declared before it can be used. In a LINQ query, from
the data source ( customers
) and scope variable ( cust
) are first introduced using clauses.
//queryAllCustomers is an IEnumerable<Customer>
var queryAllCustomers = from cust in customers select cust;
Range variables are like foreach
iteration variables in loops, but no iteration actually occurs in query expressions. When the query is executed, the range variable will act as a customers
reference to each successive element in the query. Since the type can be inferred by the compiler cust
, there is no need to specify it explicitly. let
Additional range variables can be introduced via clauses. See let clause for details .
filter
Perhaps the most common query operation is to apply a filter in the form of a Boolean expression. A filter causes a query to return only elements for which the expression is true. The result will be generated by using where
the clause. Filters actually specify which elements to exclude from the source sequence. In the following example, only those whose address is in "London" are returned customers
.
var queryLondonCustomers = from cust in customers
where cust.City == "London"
select cust;
Use familiar C# logic AND
and OR
operators where
to apply as many filter expressions as necessary within the clause. For example, to return only customers from "London" AND
whose name is "Devon", write the following code:
where cust.City == "London" && cust.Name == "Devon"
To return customers from London or Paris, write the following code:
where cust.City == "London" || cust.City == "Paris"
middleware ordering
It is often convenient to sort the returned data . orderby
clause sorts the elements in the returned sequence according to the default comparator of the type being sorted. For example, Name
the following query can be extended to sort results based on attributes. Since Name
it is a string, the default comparator will sort alphabetically from A to Z.
var queryLondonCustomers3 =
from cust in customers
where cust.City == "London"
orderby cust.Name ascending
select cust;
To sort the results in reverse order from Z to A, use orderby…descending
the clause. See orderby clause.
group
group
clauses are used to group the results obtained by the key you specify. For example, you can specify to City
group the results by so that all customers from London or Paris are in separate groups. In this case, cust.City
the key.
// queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>>
var queryCustomersByCity =
from cust in customers
group cust by cust.City;
// customerGroup is an IGrouping<string, Customer>
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (Customer customer in customerGroup)
{
Console.WriteLine(" {0}", customer.Name);
}
}
When you group
end a query with a clause, the results are listed as a list . Each element in the list is Key
an object with a member, and the elements in the list are grouped according to that key. Nested loops must be used when iterating over a query that generates a sequence of groups foreach
. The outer loop iterates through each group, and the inner loop iterates through the members of each group.
If the result of a group operation must be referenced, into
keywords can be used to create identifiers that can be queried further. The following query returns only groups containing more than two customers:
// custQuery is an IEnumerable<IGrouping<string, Customer>>
var custQuery =
from cust in customers
group cust by cust.City into custGroup
where custGroup.Count() > 2
orderby custGroup.Key
select custGroup;
connect
Join operations create associations between different sequences that are not explicitly modularized in the data source. For example, you can perform a join to find all customers and resellers with the same location. In LINQ, join
clauses always act on collections of objects, not directly on database tables.
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
In LINQ, you don't have to use it as often as you do in SQL join
, because foreign keys in LINQ are represented in the object model as properties that contain collections of items. For example Customer
object contains Order
a collection of objects. Instead of performing a join, just access the order using dot notation:
from order in Customer.Orders...
select (projection)
select
clause generates query results and specifies the "shape" or type of each returned element. For example, you can specify whether the result contains the entire Customer
object, just a member, a subset of members, or an entirely different result type based on a calculation or new object creation. When select
the clause produces something other than a copy of the source element, the operation is called projection. Transforming data using projections is a powerful feature of LINQ query expressions.
orderby clause
In a query expression, a clause can cause the returned sequence or subsequence (group) to be sorted in ascending or descending order . To perform one or more secondary sort operations, multiple keys can be specified. The default comparator for the element type performs sorting. The default sort order is ascending. It is also possible to specify a custom comparator. However, only works with method-based syntax.orderby
At compile time, orderby
the clause is translated into a call to the OrderBy method. orderby
Multiple key values in the clause will be converted to a ThenBy method call.
In the following example, the first query sorts the terms alphabetically starting with A , while the second query sorts the same terms in descending order. ( ascending
Keywords are default sort values and can be omitted.)
class OrderbySample1
{
static void Main()
{
// Create a delicious data source.
string[] fruits = { "cherry", "apple", "blueberry" };
// Query for ascending sort.
IEnumerable<string> sortAscendingQuery =
from fruit in fruits
orderby fruit //"ascending" is default
select fruit;
// Query for descending sort.
IEnumerable<string> sortDescendingQuery =
from w in fruits
orderby w descending
select w;
// Execute the query.
Console.WriteLine("Ascending:");
foreach (string s in sortAscendingQuery)
{
Console.WriteLine(s);
}
// Execute the query.
Console.WriteLine(Environment.NewLine + "Descending:");
foreach (string s in sortDescendingQuery)
{
Console.WriteLine(s);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Ascending:
apple
blueberry
cherry
Descending:
cherry
blueberry
apple
*/
The following example performs a primary sort on students' last names and then a secondary sort on their first names.
class OrderbySample2
{
// The element type of the data source.
public class Student
{
public string First { get; set; }
public string Last { get; set; }
public int ID { get; set; }
}
public static List<Student> GetStudents()
{
// Use a collection initializer to create the data source. Note that each element
// in the list contains an inner sequence of scores.
List<Student> students = new List<Student>
{
new Student {First="Svetlana", Last="Omelchenko", ID=111},
new Student {First="Claire", Last="O'Donnell", ID=112},
new Student {First="Sven", Last="Mortensen", ID=113},
new Student {First="Cesar", Last="Garcia", ID=114},
new Student {First="Debra", Last="Garcia", ID=115}
};
return students;
}
static void Main(string[] args)
{
// Create the data source.
List<Student> students = GetStudents();
// Create the query.
IEnumerable<Student> sortedStudents =
from student in students
orderby student.Last ascending, student.First ascending
select student;
// Execute the query.
Console.WriteLine("sortedStudents:");
foreach (Student student in sortedStudents)
Console.WriteLine(student.Last + " " + student.First);
// Now create groups and sort the groups. The query first sorts the names
// of all students so that they will be in alphabetical order after they are
// grouped. The second orderby sorts the group keys in alpha order.
var sortedGroups =
from student in students
orderby student.Last, student.First
group student by student.Last[0] into newGroup
orderby newGroup.Key
select newGroup;
// Execute the query.
Console.WriteLine(Environment.NewLine + "sortedGroups:");
foreach (var studentGroup in sortedGroups)
{
Console.WriteLine(studentGroup.Key);
foreach (var student in studentGroup)
{
Console.WriteLine(" {0}, {1}", student.Last, student.First);
}
}
// Keep the console window open in debug mode
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
sortedStudents:
Garcia Cesar
Garcia Debra
Mortensen Sven
O'Donnell Claire
Omelchenko Svetlana
sortedGroups:
G
Garcia, Cesar
Garcia, Debra
M
Mortensen, Sven
O
O'Donnell, Claire
Omelchenko, Svetlana
*/
select clause
In query expressions, clauses specify the types of values that will be produced when the query is executed . Evaluates the result from all previous clauses and from all expressions in the clause itself. A query expression must end with a clause or a group clause.select
select
select
The following examples demonstrate simple select
clauses in query expressions.
class SelectSample1
{
static void Main()
{
//Create the data source
List<int> Scores = new List<int>() { 97, 92, 81, 60 };
// Create the query.
IEnumerable<int> queryHighScores =
from score in Scores
where score > 80
select score;
// Execute the query.
foreach (int i in queryHighScores)
{
Console.Write(i + " ");
}
}
}
//Output: 97 92 81
select
The type of the sequence produced by the clause determines queryHighScores
the type of the query variable. In the simplest case, select
the clause specifies only scope variables. This will cause the returned sequence to contain elements of the same type as the data source. However, select
clauses also provide a powerful mechanism for transforming (or projecting) source data into new types.