8. LINQ Queries || C# 10 Flashcards
What is a LINQ?
- What it’s description?
- What kind of collection you can use LINQ on?
- In which namespace is it defined?
- LINQ (Language Integrated Query) is a set of language and runtime features for writing structured and type-safe queries over local object collections and remote data sources
- LINQ enables you to query any collection implementing
IEnumerable<T>
, whether an array, list or XML Document Object Model, as well as remote data sources (tables in SQL database) -
System.Linq
andSystem.Linq.Expressions
What is a basic units of data in LINQ? Describe that
- Sequences - any object that implements
IEnumerable<T>
- Elements - each item in the sequence
string[] names = {"Tom", "Dick", "Harry"};
names - sequence
“Tom”, “Dick” and “Harry” - elements
- What is a query operator?
- What are the members of the typical query operator?
- What is a standart query operator?
Query operator - a method that transforms a sequence. A typical query operator accepts an input sequence and emits a transformed output sequence.
Standart query operator is one of the 40 query operators that are already defined in Enumerable
class in System.Linq
What is a query?
Query is an expression that, when enumerated, transforms sequences with query operators. The simples query comprises one input sequence and one operator:
~~~
using System.Linq;
string[] names = {“Tom”, “Dick”, “Harry”};
IEnumerable<string> filteredNames = Enumerable.Where(names, n => n.Length >= 4);
~~~
or simply
~~~
names.Where(w => w.Length >= 4);
~~~</string>
What is a fluent syntax in LINQ?
Fluent syntax is the most flexible and fundamental. It is achieved by chaining query operators one after another and the output of one operator is the input of the next:
~~~
var names = {“Tom”, “Jim”, “Harry”};
var query = names
.Where(w => w.Contains(“a”))
.OderBy(o => o.Length)
.Select(s => s.ToUpper());
~~~
// HARRY
How the compiler would translate this?
~~~
var names = {“Tom”, “Jim”, “Harry”};
var query = names
.Where(w => w.Contains(“a”))
.OderBy(o => o.Length)
.Select(s => s.ToUpper());
~~~
How is it called?
var names = {"Tom", "Jim", "Harry"}; IEnumerable<string> filtered = Enumerable.Where(w => w.Contains("a")); IEnumerable<string> ordered = Enumerable.OderBy(o => o.Length); IEnumerable<string> upperCased = Enumerable.Select(s => s.ToUpper());
Compiler would use the standart query operators (Enumerable.Where) and apply progressive syntax (each query as new variable)
How does the insides of a query operator called?
Be specific
If we take Enumerable.Where(w => w.Contains("a");
the w => w.Contains("a")
part is a Lambda expression. And if Lambda expression takes a value and returns a bool value (as it does here) it is called a Predicate
Write a query expression in query syntax where items in the given list would be filtered by containing letter, sorted alphabetically and then changed to be upper case
Lets say we are given this array:string [] names = {"Linda", "Ewa", "Arnas", "Simon", "Patrik", "Oscar"};
Our query (in query syntax) would look like this:
~~~
IEnumerable<string> query =
from names n in names
where w.Contains("a")
orderby o.Length
select s.ToUpper();
~~~
Query expressions always start with *from* clause (aka range variable) and end with either a *select* or *group* clause</string>
Result: EWA, ARNAS, LINDA, OSCAR, PATRIK
Compare LINQ syntax vs. SQL syntax
- Variables: In LINQ you cannot use a variable before you declare it. In SQL, you can reference a table alias in the SELECT clause before defining it in a FROM clause
- Subqueries: In LINQ is just another C# expression and so requires no special syntax. In SQL subqueries are subject to special rules.
- Logic flow: With LINQ, data logically flows from left to right through a query. With SQL, the order is less well structured with regards to data flow
- Query composition: A LINQ comprises a conveyor belt or pipeline of operators that accept and emit sequences whose element order can matter. An SQL query comprises a network of clauses that work mostly with unordered sets.
Can you mix query syntaxes in a query?
Yes you can.
If we have this starting array: string [] names = {"Linda", "Ewa", "Arnas", "Simon", "Patrik", "Oscar"};
we can combine syntaxes to find out how many names in this array contais a letter ‘a’:int matches = (from n in names where w.Contains("a") select s).Count();
Result : 5
What is a deffered or lazy execution in LINQ?
In LINQ, “deferred execution” or “lazy execution” refers to the way that a LINQ query is executed. With deferred execution, the query is not executed until it is actually needed to produce a result. The query is stored as a expression tree and is executed only when the query is enumerated, for example, by calling ToList()
, First()
, Count()
, or by iterating through the result using a foreach loop.
The main advantage of deferred execution is that it allows you to perform operations on the query without actually executing it until the results are actually needed. This can lead to improved performance and reduced resource utilization because the query is executed only when it is necessary to produce the result, and not before.
How the query operators can be specified based on their behaviour to the query?
Give a definition an an example for each
-
Decorators - query operators which modify or decorate the behavior of a query. Examples would be
.Where(w => w.Id == "1")
. When we apply this instead of full query result we will get only ones that comply with the filter we just wrote. That is how we are modifying the behaviour of query. -
Proxies - A query operator can also be referred to as a “proxy” when it acts as a placeholder for the actual data that will be retrieved when the query is executed. For example, the
.AsEnumerable()
operator can be considered a proxy because it converts a query that is based on a specific data source, such as an IQueryable instance, into a query that is based on an IEnumerable instance.
What are the three strategies for building more complex queries?
- Progressive query construction;
- Using the
into
keyword; - Wrapping queries;
How can we use anonymous types in our LINQ query?
So let’s say we want to save unchanged array to one parameter and changed array to another parameter, without having to create one-off class for only that.
Our starter array:string[] names = {"Tom", "Jim", "Harry", "Mary", "Jay"};
We then can write this anonymous query like this (note that after select new
we don’t specify which specific type we are creating):
~~~
var intermediate = from n in names
select new
{
Original = n,
Vowelless = n.Replace(“a”, “”).Replace(“e”, “”)
};
```
variable “intermediate” needs to be declared with ‘var’ here
Define differences between ‘into’ keyword and ‘let’ keyword in LINQ queries
The into
and let
keywords are used in LINQ (Language Integrated Query) to modify intermediate results in a query. The main difference between them lies in what they allow you to do in the query.
The let
keyword is used to introduce a new range variable and to assign it a value based on the current range variables. For example:
~~~
var result = from x in source
let y = x + 1
select y;
In the above example, the `let` keyword is used to introduce a new range variable y, which is assigned the value of x + 1. This allows you to perform additional operations on the result before returning it. The `into` keyword is used to continue a query into another query expression. For example:
var finalResult = from x in source
where x > 10
into y
where y < 20
select y;
~~~