Skip to content

Commit

Permalink
Updated LINQ topics for C# Concepts section (#1302)
Browse files Browse the repository at this point in the history
* Updated LINQ topics for C# Concepts section

Phase one - additional topics will be moved from the Programming Guide
later

* Fixed build errors

* Addressed feedback

* Created a LINQ folder and moved the files; updated links

* Updated TOC with new path

* Updated redirect URLs

* Fixed one more redirect
  • Loading branch information
stevehoag committed Dec 12, 2016
1 parent 0293858 commit 97a29e6
Show file tree
Hide file tree
Showing 96 changed files with 3,031 additions and 1,653 deletions.
25 changes: 0 additions & 25 deletions docs/csharp/linq.md

This file was deleted.

29 changes: 29 additions & 0 deletions docs/csharp/linq/create-a-nested-group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: "Create a nested group"
description: How to create a nested group.
keywords: .NET, .NET Core, C#
author: stevehoag
manager: wpickett
ms.author: wiwagn
ms.date: 12/1/2016
ms.topic: article
ms.prod: .net-core
ms.technology: .net-core-technologies
ms.devlang: dotnet
ms.assetid: e9f00708-362e-4d13-98c5-d77549347ba0
---
# Create a nested group

The following example shows how to create nested groups in a LINQ query expression. Each group that is created according to student year or grade level is then further subdivided into groups based on the individuals' names.

## Example

> [!NOTE]
> This example contains references to objects that are defined in the sample code in [Query a collection of objects](query-a-collection-of-objects.md).
[!code-cs[csProgGuideLINQ#24](../../../samples/snippets/csharp/concepts/linq/how-to-create-a-nested-group_1.cs)]

Note that three nested `foreach` loops are required to iterate over the inner elements of a nested group.

## See also
[LINQ Query Expressions](index.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: "Dynamically specify predicate filters at runtime"
description: How to dynamically specify predicate filters at runtime.
keywords: .NET, .NET Core, C#
author: stevehoag
manager: wpickett
ms.author: wiwagn
ms.date: 12/1/2016
ms.topic: article
ms.prod: .net-core
ms.technology: .net-core-technologies
ms.devlang: dotnet
ms.assetid: 90238470-0767-497c-916c-52d0d16845e0
---
# Dynamically specify predicate filters at runtime

In some cases you do not know until run time how many predicates you have to apply to source elements in the `where` clause. One way to dynamically specify multiple predicate filters is to use the <xref:System.Linq.Enumerable.Contains%2A> method, as shown in the following example. The example is constructed in two ways. First, the project is run by filtering on values that are provided in the program. Then the project is run again by using input provided at run time.

## To filter by using the Contains method

1. Open a new console application and name it `PredicateFilters`.

2. Copy the `StudentClass` class from [Query a collection of objects](query-a-collection-of-objects.md) and paste it into namespace `PredicateFilters` underneath class `Program`. `StudentClass` provides a list of `Student` objects.

3. Comment out the `Main` method in `StudentClass`.

4. Replace class `Program` with the following code.

[!code-cs[csProgGuideLINQ#26](../../../samples/snippets/csharp/concepts/linq/how-to-dynamically-specify-predicate-filters-at-runtime_1.cs)]

5. Add the following line to the `Main` method in class `DynamicPredicates`, under the declaration of `ids`.

```cs
QueryById(ids);
```

6. Run the project.

7. The following output is displayed in a console window:

Garcia: 114

O'Donnell: 112

Omelchenko: 111

8. The next step is to run the project again, this time by using input entered at run time instead of array `ids`. Change `QueryByID(ids)` to `QueryByID(args)` in the `Main` method.

9. Run the project with the command line arguments `122 117 120 115`. When the project is run, those values become elements of `args`, the parameter of the `Main` method..

10. The following output is displayed in a console window:

Adams: 120

Feng: 117

Garcia: 115

Tucker: 122

## To filter by using a switch statement

1. You can use a `switch` statement to select among predetermined alternative queries. In the following example, `studentQuery` uses a different `where` clause depending on which grade level, or year, is specified at run time.

2. Copy the following method and paste it into class `DynamicPredicates`.

[!code-cs[csProgGuideLINQ#27](../../../samples/snippets/csharp/concepts/linq//how-to-dynamically-specify-predicate-filters-at-runtime_2.cs)]
3. In the `Main` method, replace the call to `QueryByID` with the following call, which sends the first element from the `args` array as its argument: `QueryByYear(args[0])`.

4. Run the project with a command line argument of an integer value between 1 and 4.


## See Also
[LINQ Query Expressions](index.md)
[where clause](../language-reference/keywords/where-clause.md)
81 changes: 81 additions & 0 deletions docs/csharp/linq/group-query-results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
title: "Group query results"
description: How to group results.
keywords: .NET, .NET Core, C#
author: stevehoag
manager: wpickett
ms.author: wiwagn
ms.date: 12/1/2016
ms.topic: article
ms.prod: .net-core
ms.technology: .net-core-technologies
ms.devlang: dotnet
ms.assetid: 2e4ec27f-06fb-4de7-8973-0189906d4520
---
# Group query results

Grouping is one of the most powerful capabilities of LINQ. The following examples show how to group data in various ways:

- By a single property.

- By the first letter of a string property.

- By a computed numeric range.

- By Boolean predicate or other expression.

- By a compound key.

In addition, the last two queries project their results into a new anonymous type that contains only the student's first and last name. For more information, see the [group clause](../language-reference/keywords/group-clause.md).

## Example
All the examples in this topic use the following helper classes and data sources.

[!code-cs[csProgGuideLINQ#15](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_1.cs)]

## Example
The following example shows how to group source elements by using a single property of the element as the group key. In this case the key is a `string`, the student's last name. It is also possible to use a substring for the key. The grouping operation uses the default equality comparer for the type.

Paste the following method into the `StudentClass` class. Change the calling statement in the `Main` method to `sc.GroupBySingleProperty()`.

[!code-cs[csProgGuideLINQ#17](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_2.cs)]

## Example
The following example shows how to group source elements by using something other than a property of the object for the group key. In this example, the key is the first letter of the student's last name.

Paste the following method into the `StudentClass` class. Change the calling statement in the `Main` method to `sc.GroupBySubstring()`.

[!code-cs[csProgGuideLINQ#18](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_3.cs)]

## Example
The following example shows how to group source elements by using a numeric range as a group key. The query then projects the results into an anonymous type that contains only the first and last name and the percentile range to which the student belongs. An anonymous type is used because it is not necessary to use the complete `Student` object to display the results. `GetPercentile` is a helper function that calculates a percentile based on the student's average score. The method returns an integer between 0 and 10.

[!code-cs[csProgGuideLINQ#50](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_4.cs)]

Paste the following method into the `StudentClass` class. Change the calling statement in the `Main` method to `sc.GroupByRange()`.

[!code-cs[csProgGuideLINQ#19](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_5.cs)]

## Example
The following example shows how to group source elements by using a Boolean comparison expression. In this example, the Boolean expression tests whether a student's average exam score is greater than 75. As in previous examples, the results are projected into an anonymous type because the complete source element is not needed. Note that the properties in the anonymous type become properties on the `Key` member and can be accessed by name when the query is executed.

Paste the following method into the `StudentClass` class. Change the calling statement in the `Main` method to `sc.GroupByBoolean()`.

[!code-cs[csProgGuideLINQ#20](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_6.cs)]

## Example
The following example shows how to use an anonymous type to encapsulate a key that contains multiple values. In this example, the first key value is the first letter of the student's last name. The second key value is a Boolean that specifies whether the student scored over 85 on the first exam. You can order the groups by any property in the key.

Paste the following method into the `StudentClass` class. Change the calling statement in the `Main` method to `sc.GroupByCompositeKey()`.

[!code-cs[csProgGuideLINQ#21](../../../samples/snippets/csharp/concepts/linq/how-to-group-query-results_7.cs)]

## See also
<xref:System.Linq.Enumerable.GroupBy%2A>
<xref:System.Linq.IGrouping%602>
[LINQ Query Expressions](index.md)
[group clause](../language-reference/keywords/group-clause.md)
[Anonymous Types](../programming-guide/classes-and-structs/anonymous-types.md)
[Perform a Subquery on a Grouping Operation](perform-a-subquery-on-a-grouping-operation.md)
[Create a Nested Group](create-a-nested-group.md)
[Grouping Data](../programming-guide/concepts/linq/grouping-data.md)
55 changes: 55 additions & 0 deletions docs/csharp/linq/group-results-by-contiguous-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: "Group results by contiguous keys"
description: How to group results by contiguous keys.
keywords: .NET, .NET Core, C#
author: stevehoag
manager: wpickett
ms.author: wiwagn
ms.date: 12/1/2016
ms.topic: article
ms.prod: .net-core
ms.technology: .net-core-technologies
ms.devlang: dotnet
ms.assetid: cbda9c08-151b-4c9e-82f7-c3d7f3dac66b
---
# Group results by contiguous keys

The following example shows how to group elements into chunks that represent subsequences of contiguous keys. For example, assume that you are given the following sequence of key-value pairs:

|Key|Value|
|---------|-----------|
|A|We|
|A|think|
|A|that|
|B|Linq|
|C|is|
|A|really|
|B|cool|
|B|!|

The following groups will be created in this order:

1. We, think, that

2. Linq

3. is

4. really

5. cool, !

The solution is implemented as an extension method that is thread-safe and that returns its results in a streaming manner. In other words, it produces its groups as it moves through the source sequence. Unlike the `group` or `orderby` operators, it can begin returning groups to the caller before all of the sequence has been read.

Thread-safety is accomplished by making a copy of each group or chunk as the source sequence is iterated, as explained in the source code comments. If the source sequence has a large sequence of contiguous items, the common language runtime may throw an <xref:System.OutOfMemoryException>.

## Example
The following example shows both the extension method and the client code that uses it.

[!code-cs[cscsrefContiguousGroups#1](../../../samples/snippets/csharp/concepts/linq/how-to-group-results-by-contiguous-keys_1.cs)]

To use the extension method in your project, copy the `MyExtensions` static class to a new or existing source code file and if it is required, add a `using` directive for the namespace where it is located.

## See also
[LINQ Query Expressions](index.md)

37 changes: 37 additions & 0 deletions docs/csharp/linq/handle-exceptions-in-query-expressions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: "Handle exceptions in query expressions"
description: How to handle exceptions in query expressions.
keywords: .NET, .NET Core, C#
author: stevehoag
manager: wpickett
ms.author: wiwagn
ms.date: 12/1/2016
ms.topic: article
ms.prod: .net-core
ms.technology: .net-core-technologies
ms.devlang: dotnet
ms.assetid: 2bf0c397-13fb-4f68-bc2b-531c6c88a167
---
# Handle exceptions in query expressions

It is possible to call any method in the context of a query expression. However, we recommend that you avoid calling any method in a query expression that can create a side effect such as modifying the contents of the data source or throwing an exception. This example shows how to avoid raising exceptions when you call methods in a query expression without violating the general .NET Framework guidelines on exception handling. Those guidelines state that it is acceptable to catch a specific exception when you understand why it will be thrown in a given context. For more information, see [Best Practices for Exceptions](http://msdn.microsoft.com/library/f06da765-235b-427a-bfb6-47cd219af539).

The final example shows how to handle those cases when you must throw an exception during execution of a query.

## Example

The following example shows how to move exception handling code outside a query expression. This is only possible when the method does not depend on any variables local to the query.

[!code-cs[csProgGuideLINQ#10](../../../samples/snippets/csharp/concepts/linq/how-to-handle-exceptions-in-query-expressions_1.cs)]

## Example

In some cases, the best response to an exception that is thrown from within a query might be to stop the query execution immediately. The following example shows how to handle exceptions that might be thrown from inside a query body. Assume that `SomeMethodThatMightThrow` can potentially cause an exception that requires the query execution to stop.

Note that the `try` block encloses the `foreach` loop, and not the query itself. This is because the `foreach` loop is the point at which the query is actually executed. For more information, see [Introduction to LINQ queries](../programming-guide/concepts/linq/introduction-to-linq-queries.md).

[!code-cs[csProgGuideLINQ#12](../../../samples/snippets/csharp/concepts/linq/how-to-handle-exceptions-in-query-expressions_2.cs)]


## See Also
[LINQ query expressions](index.md)
36 changes: 36 additions & 0 deletions docs/csharp/linq/handle-null-values-in-query-expressions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: "Handle null values in query expressions"
description: How to handle null values in query expressions.
keywords: .NET, .NET Core, C#
author: stevehoag
manager: wpickett
ms.author: wiwagn
ms.date: 12/1/2016
ms.topic: article
ms.prod: .net-core
ms.technology: .net-core-technologies
ms.devlang: dotnet
ms.assetid: ac63ae8b-724d-4251-9334-528f4e884ae7
---
# Handle null values in query expressions

This example shows how to handle possible null values in source collections. An object collection such as an <xref:System.Collections.Generic.IEnumerable%601> can contain elements whose value is [null](../language-reference/keywords/null.md). If a source collection is null or contains an element whose value is null, and your query does not handle null values, a <xref:System.NullReferenceException> will be thrown when you execute the query.

## Example

You can code defensively to avoid a null reference exception as shown in the following example:

[!code-cs[csProgGuideLINQ#82](../../../samples/snippets/csharp/concepts/linq/how-to-handle-null-values-in-query-expressions_1.cs)]

In the previous example, the `where` clause filters out all null elements in the categories sequence. This technique is independent of the null check in the join clause. The conditional expression with null in this example works because `Products.CategoryID` is of type `int?` which is shorthand for `Nullable<int>`.

## Example

In a join clause, if only one of the comparison keys is a nullable value type, you can cast the other to a nullable type in the query expression. In the following example, assume that `EmployeeID` is a column that contains values of type `int?`:

[!code-cs[csProgGuideLINQ#83](../../../samples/snippets/csharp/concepts/linq/how-to-handle-null-values-in-query-expressions_2.cs)]

## See also
<xref:System.Nullable%601>
[LINQ query expressions](index.md)
[Nullable types](../programming-guide/nullable-types/index.md)
Loading

0 comments on commit 97a29e6

Please sign in to comment.