IQueryable derives from IEnumerable changing it's behaviour drastically
For example following code:
1: 2: |
|
may be translated to:
1: 2: 3: |
|
Step 1:
1: 2: |
|
translated by C# compiler to:
1: 2: 3: 4: 5: |
|
Step 2:
1: 2: 3: 4: 5: |
|
Then expression trees stud => stud.City == "Kiev"
would be translated to:
1: 2: 3: 4: 5: 6: |
|
Which graphically whould be represented as:
The only purpose to represent code as data which in future may be translated in other language
Object-Relational Mapping (ORM) which allows you:
It is a bridge between your domain or entity classes and the database.
DbContext contains entity set (DbSet<TEntity>
) for all the entities which is mapped to DB tables
It keeps track of changes occurred in the entities after it has been querying from the database
DbContext does first level caching by default. It stores the entities which has been retrieved during the life time of a context class.
DbContext converts LINQ-to-Entities queries to SQL query and send it to the database.
It also performs the Insert, update and delete operations to the database, based on the entity states.
Example:
1: 2: |
|
You already saw this query. But in this case ctx
is instance of DbContext.
Execute not when constructed, but when enumerated (when MoveNext is called)
All standard query operators provide deferred execution, with the following exceptions:
First
Count
ToArray
ToList
ToDictionary
ToLookup
IEnumerable is cool when it is used for right job. In some cases it can introduce performance overhead:
Please do not write such "magnificent code":
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
|
Other way to avoid it could be just cache result of execution with ToList
or ToArray
and get needed element by indexer;
Or choose right parameter type for your method:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: |
|
In this case to avoid multiple enumeration just use built-in method Zip
:
1: 2: 3: 4: 5: 6: 7: 8: 9: |
|
LINQ queries do not provide any particular order unless you specify some
You can sort in acsending order using orderby
syntax:
1: 2: 3: |
|
or
1:
|
|
In order to sort in descending order you need to write 'descending' keyword:
1: 2: 3: |
|
or
1:
|
|
Note that there is possibility to write dependent ordering:
1: 2: 3: |
|
or
1: 2: |
|
Used when you need to precess several items grouping them by some criterea:
1: 2: |
|
or
1:
|
|
Inner join returns only those records or rows that match or exists in both the sources.
1: 2: 3: |
|
We can match items by complex criterea using anonymous types:
1: 2: 3: |
|
A group join produces a sequence of object arrays based on properties equivalence of left collection and right collection. If right collection has no matching elements with left collection then an empty array will be produced.
1: 2: 3: |
|
LEFT JOIN returns all records or rows from left table and from right table returns only matched records. If there are no columns matching in the right table, it returns NULL values.
1: 2: 3: 4: |
|
Cross join returns records or rows that are multiplication of record number from both the tables means each row on left table will related to each row of right table
1: 2: 3: |
|
Aggregators are extensions that return some single result which is not collection, in other words they are mostly statistical operators
Returns a count of elements which satisfy passed condition (can be ommited):
1: 2: |
|
1: 2: |
|
Can be more complex:
1:
|
|
1: 2: 3: |
|
1: 2: |
|
Performs custom aggregation:
1: 2: |
|
1: 2: |
|
1: 2: |
|
1: 2: |
|
1: 2: 3: |
|
1: 2: 3: 4: |
|
1: 2: 3: 4: 5: 6: 7: 8: 9: |
|
Additional resources: