diff --git a/101-linq-samples/docs/aggregates-1.md b/101-linq-samples/docs/aggregates-1.md new file mode 100644 index 0000000..801a658 --- /dev/null +++ b/101-linq-samples/docs/aggregates-1.md @@ -0,0 +1,28 @@ +# LINQ - Aggregators + +*Aggregator* methods return a single value calculated from all the elements in a sequence. the aggregator methods include `Count`, `Sum`, `Min`, `Max`, `Average`, and `Aggregate`. + +## Sum all numeric elements in a sequence + +This sample uses `Sum` to get the total of the numbers in an array. + +``` cs --region sum-syntax --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Sum a projection from a sequence + +This sample uses `Sum` to get the total number of characters of all words in the array. + +``` cs --region sum-of-projection --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Sum all elements that are members of a group + +This sample uses `Sum` to get the total units in stock for each product category. + +``` cs --region grouped-sum --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Aggregates-Min »](./aggregates-2.md) Previous: [Aggregates »](./aggregates.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/aggregates-2.md b/101-linq-samples/docs/aggregates-2.md new file mode 100644 index 0000000..c559f60 --- /dev/null +++ b/101-linq-samples/docs/aggregates-2.md @@ -0,0 +1,35 @@ +# LINQ - Aggregators + +*Aggregator* methods return a single value calculated from all the elements in a sequence. the aggregator methods include `Count`, `Sum`, `Min`, `Max`, `Average`, and `Aggregate`. + +## Find the minimum of a sequence of elements + +This sample uses `Min` to get the lowest number in an array. + +``` cs --region min-syntax --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the minimum of a projection + +This sample uses `Min` to get the length of the shortest word in an array. + +``` cs --region min-projection --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the minimum in each group + +This sample uses `Min` to get the cheapest price among each category's products. + +``` cs --region min-grouped --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find all elements matching the minimum + +This sample uses `Min` to get the products with the cheapest price in each category. + +``` cs --region min-each-group --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Aggregates-Max »](./aggregates-3.md) Previous: [Aggregates-Sum »](./aggregates-1.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/aggregates-3.md b/101-linq-samples/docs/aggregates-3.md new file mode 100644 index 0000000..9c1edaa --- /dev/null +++ b/101-linq-samples/docs/aggregates-3.md @@ -0,0 +1,35 @@ +# LINQ - Aggregators + +*Aggregator* methods return a single value calculated from all the elements in a sequence. the aggregator methods include `Count`, `Sum`, `Min`, `Max`, `Average`, and `Aggregate`. + +## Find the maximun of a sequence of elements + +This sample uses `Max` to get the highest number in an array. + +``` cs --region max-syntax --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the maximum of a projection + +This sample uses `Max` to get the length of the longest word in an array. + +``` cs --region max-projection --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the maximum in each group + +This sample uses `Max` to get the most expensive price among each category's products. + +``` cs --region max-grouped --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find all elements matching the maximum + +This sample uses `Max` to get the products with the most expensive price in each category. + +``` cs --region max-each-group --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Aggregates-Average »](./aggregates-4.md) Previous: [Aggregates-Min »](./aggregates-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/aggregates-4.md b/101-linq-samples/docs/aggregates-4.md new file mode 100644 index 0000000..779043e --- /dev/null +++ b/101-linq-samples/docs/aggregates-4.md @@ -0,0 +1,42 @@ +# LINQ - Aggregators + +*Aggregator* methods return a single value calculated from all the elements in a sequence. the aggregator methods include `Count`, `Sum`, `Min`, `Max`, `Average`, and `Aggregate`. + +## Find the average of a sequence of elements + +This sample uses `Average` to get the average of all numbers in an array. + +``` cs --region average-syntax --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the average of a projection + +This sample uses `Average` to get the average length of the words in the array. + +``` cs --region average-projection --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the average in each group + +This sample uses `Average` to get the average price of each category's products. + +``` cs --region average-grouped --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Compute an aggregate value from all elements of a sequence + +This sample uses `Aggregate` to create a running product on the array that calculates the total product of all elements. + +``` cs --region aggregate-syntax --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Compute an aggregate value from a seed value and all elements of a sequence + +This sample uses `Aggregate` to create a running account balance that subtracts each withdrawal from the initial balance of 100, as long as the balance never drops below 0. + +``` cs --region aggregate-seeded --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Sequence operations »](./sequence-operations.md) Previous: [Aggregates-Min »](./aggregates-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/aggregates.md b/101-linq-samples/docs/aggregates.md new file mode 100644 index 0000000..2911afb --- /dev/null +++ b/101-linq-samples/docs/aggregates.md @@ -0,0 +1,36 @@ +# LINQ - Aggregators + +*Aggregator* methods return a single value calculated from all the elements in a sequence. the aggregator methods include `Count`, `Sum`, `Min`, `Max`, `Average`, and `Aggregate`. + +## Count all elements in a sequence + +This sample uses `Count` to get the number of unique factors of 300. + +``` cs --region count-syntax --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Count all elements matching a condition + +This sample uses `Count` to get the number of odd ints in the array. + + +``` cs --region count-conditional --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Count all elements nested in a query + +This sample uses `Count` to return a list of customers and how many orders each has. + +``` cs --region nested-count --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Count all elements that are members of a group + +This sample uses `Count` to return a list of categories and how many products each has. + +``` cs --region grouped-count --source-file ../src/AggregateOperators.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Aggregates-Sum »](./aggregates-1.md) Previous: [Quantifiers »](./generators.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/conversions.md b/101-linq-samples/docs/conversions.md new file mode 100644 index 0000000..f22c9db --- /dev/null +++ b/101-linq-samples/docs/conversions.md @@ -0,0 +1,35 @@ +# LINQ - Conversion Operators + +The methods `ToArray`, `ToArray`, `ToDictionary`, and `OfType` provide ways to convert LINQ results to collections. + +## Convert to an array + +This sample uses `ToArray` to immediately evaluate a sequence into an array. + +``` cs --region convert-to-array --source-file ../src/Conversions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Convert to a list + +This sample uses `ToList` to immediately evaluate a sequence into a `List`. + +``` cs --region convert-to-list --source-file ../src/Conversions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Convert to a dictionary + +This sample uses `ToDictionary` to immediately evaluate a sequence and a related key expression into a dictionary. + +``` cs --region convert-to-dictionary --source-file ../src/Conversions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Convert elements that match a type + +This sample uses `OfType` to return only the elements of the array that are of type `double`. + +``` cs --region convert-to-type --source-file ../src/Conversions.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Element operations »](./elements.md) Previous: [Intersect and except set operations »](./sets-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/elements.md b/101-linq-samples/docs/elements.md new file mode 100644 index 0000000..02ea622 --- /dev/null +++ b/101-linq-samples/docs/elements.md @@ -0,0 +1,42 @@ +# LINQ - Element Operators + +The methods `First`, `FirstOrDefault`, and `ElementAt` provide ways to select a single element by position. + +## Find the first element + +This sample uses `First` to return the first matching element as a `Product`, instead of as a sequence containing a `Product`. + +``` cs --region first-element --source-file ../src/ElementOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the first matching element + +This sample uses `First` to find the first element in the array that starts with 'o'. + +``` cs --region first-matching-element --source-file ../src/ElementOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## First element of a possibly empty sequence + +This sample uses `FirstOrDefault` to try to return the first element of the sequence, unless there are no elements, in which case the default value for that type is returned. + +``` cs --region first-or-default --source-file ../src/ElementOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## First matching element or default + +This sample uses `FirstOrDefault` to return the first product whose `ProductID` is `789` as a single `Product` object, unless there is no match, in which case `null` is returned. + +``` cs --region first-matching-or-default --source-file ../src/ElementOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find element at position + +This sample uses `ElementAt` to retrieve the second number greater than 5 from an array. + +``` cs --region element-at --source-file ../src/ElementOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Generate sequences »](./generators.md) Previous: [Conversion operations »](./conversions.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/generators.md b/101-linq-samples/docs/generators.md new file mode 100644 index 0000000..938bbe8 --- /dev/null +++ b/101-linq-samples/docs/generators.md @@ -0,0 +1,21 @@ +# LINQ - Generate elements + +The methods `Range` and `Repeat` create sequences of integers. These can be the source sequences of queries. + +## Create a range of numbers + +This sample uses `First` to return the first matching element as a `Product`, instead of as a sequence containing a `Product`. + +``` cs --region generate-range --source-file ../src/Generators.cs --project ../src/Try101LinqSamples.csproj +``` + +## Repeat the same number + +This sample uses `First` to find the first element in the array that starts with 'o'. + +``` cs --region generate-repeat --source-file ../src/Generators.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Quantifying operations »](./quantifiers.md) Previous: [Conversion operations »](./conversions.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/groupings-2.md b/101-linq-samples/docs/groupings-2.md new file mode 100644 index 0000000..c330cee --- /dev/null +++ b/101-linq-samples/docs/groupings-2.md @@ -0,0 +1,18 @@ +# LINQ - Grouping Operators with custom comparer + +The `group by` and `into` can use custom comparers to separate groups. + +These samples use the following custom comparer. It compares two strings to see if they are anagrams. (Anagrams are pairs of words formed from the same letters.) + +``` cs --region anagram-comparer --session groupby-custom-comparer --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Groupby with a custom comparer + + +``` cs --region groupby-custom-comparer --session groupby-custom-comparer --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Nested groupings with a custom comparer »](./groupings-3.md) Previous: [Groupings «](./groupings.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/groupings-3.md b/101-linq-samples/docs/groupings-3.md new file mode 100644 index 0000000..47115ab --- /dev/null +++ b/101-linq-samples/docs/groupings-3.md @@ -0,0 +1,18 @@ +# LINQ - Nested Grouping Operators with custom comparer + +The `group by` and `into` can use custom comparers to separate groups. These queries can be nested. + +These samples use the following custom comparer. It compares two strings to see if they are anagrams. (Anagrams are pairs of words formed from the same letters.) + +``` cs --region anagram-comparer --session nested-groupby-custom --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Groupby with a custom comparer + + +``` cs --region nested-groupby-custom --session nested-groupby-custom --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Set operations »](./sets.md) Previous: [Groupings with a custom comparer «](./orderings-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/groupings.md b/101-linq-samples/docs/groupings.md new file mode 100644 index 0000000..2a445da --- /dev/null +++ b/101-linq-samples/docs/groupings.md @@ -0,0 +1,35 @@ +# LINQ - Grouping Operators + +The `group by` and `into` keywords provide grouping constructs to organize elements of the input sequence into buckets. + +## Group by into buckets + +This sample demonstrates the use of `group by` and `into` to create buckets based on the remainder of an integer when dividing it by 5. + +``` cs --region groupby-syntax --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Groupby using a property + +This sample uses `group by` to partition a list of words by their first letter. + +``` cs --region groupby-property --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Grouping using a key property + +This sample uses `group by` to partition a list of products by category. + +``` cs --region groupby-category --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Nested group by queries + +This sample demonstrates the use of `group by` and `into` nested buckets of orders by customer, year, and month. The result + +``` cs --region nested-groupby --source-file ../src/Groupings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Grouping with a custom comparer »](./groupings-2.md) Previous: [Nested custom comparisons «](./orderings-5.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/join-operators.md b/101-linq-samples/docs/join-operators.md new file mode 100644 index 0000000..d137586 --- /dev/null +++ b/101-linq-samples/docs/join-operators.md @@ -0,0 +1,35 @@ +# LINQ - Join operations + +Learn to use cross `join`, group `join`, and left outer `join` operations in LINQ queries + +## Cross join + +This sample shows how to efficiently join elements of two sequences based on equality between key expressions over the two. + +``` cs --region cross-join --source-file ../src/JoinOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Group join + +Using a group `join` you can get all the products that match a given category bundled as a sequence. + +``` cs --region group-join --source-file ../src/JoinOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Cross join with group join + +The group `join` operator is more general than `join`, as this slightly more verbose version of the cross `join` sample shows. + +``` cs --region cross-group-join --source-file ../src/JoinOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Left outer join using group join + +A so-called outer join can be expressed with a `group join`. A left outer join is like a cross join, except that all the left hand side elements get included at least once, even if they don't match any right hand side elements. Note how `Vegetables` shows up in the output even though it has no matching products. + +``` cs --region left-outer-join --source-file ../src/JoinOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +**Previous: [Query execution »](./query-execution.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/orderings-2.md b/101-linq-samples/docs/orderings-2.md new file mode 100644 index 0000000..a444047 --- /dev/null +++ b/101-linq-samples/docs/orderings-2.md @@ -0,0 +1,21 @@ +# LINQ - Ordering Operators + +The `orderby` clause of a LINQ query sorts the output sequence. You can control the properties used for sorting, and specify ascending or descending order. + +## orderby descending + +This sample uses `orderby` and `descending` to sort a list of doubles from highest to lowest. + +``` cs --region orderbydescending-syntax --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Descending ordering user defined types + +This sample uses `orderby` to sort a list of products by units in stock from highest to lowest. + +``` cs --region orderby-descending-type --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Orderby then by »](./orderings-3.md) Previous: [Ordering «](./orderings.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/orderings-3.md b/101-linq-samples/docs/orderings-3.md new file mode 100644 index 0000000..f49ac64 --- /dev/null +++ b/101-linq-samples/docs/orderings-3.md @@ -0,0 +1,28 @@ +# LINQ - Ordering Operators + +The `orderby` clause of a LINQ query sorts the output sequence. You can control the properties used for sorting, and specify ascending or descending order. + +## orderby multiple properties + +This sample uses a compound `orderby` to sort a list of digits, first by length of their name, and then alphabetically by the name itself. + +``` cs --region thenby-syntax --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Multiple ordering descending + +This sample uses a compound `orderby` to sort a list of products, first by category, and then by unit price, from highest to lowest. + +``` cs --region thenby-ordering --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Reverse the sequence + +This sample uses `Reverse` to create a list of all digits in the array whose second letter is 'i' that is reversed from the order in the original array. + +``` cs --region reverse --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Custom comparisons »](./orderings-4.md) Previous: [Ordering descending «](./orderings-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/orderings-4.md b/101-linq-samples/docs/orderings-4.md new file mode 100644 index 0000000..aa2f1b0 --- /dev/null +++ b/101-linq-samples/docs/orderings-4.md @@ -0,0 +1,24 @@ +# Using a custom comparer + +The samples on this page use the following custom comparer: + +``` cs --region custom-comparer --session orderby-custom --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Ordering with a custom comparer + +This sample orders the customers using the custom comparer + +``` cs --region orderby-custom-comparer --session orderby-custom --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Descending orders with a custom comparer + +This sample uses an `OrderBy` clause with a custom comparer to do a case-insensitive descending sort of the words in an array. + +``` cs --region desc-custom-comparer --session orderby-custom-descending --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Nested custom comparisons »](./orderings-5.md) Previous: [Orderby thenby «](./orderings-3.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/orderings-5.md b/101-linq-samples/docs/orderings-5.md new file mode 100644 index 0000000..919e2e6 --- /dev/null +++ b/101-linq-samples/docs/orderings-5.md @@ -0,0 +1,24 @@ +# Using a custom comparer on multiple sort orderings + +The samples on this page use the following custom comparer: + +``` cs --region custom-comparer --session orderby-custom-thenby --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Multiple ordering with a custom comparer + +This sample uses an `OrderBy` and a `ThenBy` clause with a custom comparer to sort first by word length and then by a case-insensitive sort of the words in an array. + +``` cs --region thenby-custom --session orderby-custom-thenby --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Multiple descending order with a custom comparer + +This sample uses an `OrderBy` and a `ThenBy` clause with a custom comparer to sort first by word length and then by a case-insensitive sort of the words in an array. + +``` cs --region thenby-custom-descending --session orderby-custom-descending-thenby --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Grouping operators »](./groupings.md) Previous: [Custom comparisons «](./orderings-4.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/orderings.md b/101-linq-samples/docs/orderings.md new file mode 100644 index 0000000..2b9924a --- /dev/null +++ b/101-linq-samples/docs/orderings.md @@ -0,0 +1,28 @@ +# LINQ - Ordering Operators + +The `orderby` clause of a LINQ query sorts the output sequence. You can control the properties used for sorting, and specify ascending or descending order. + +## orderby sorts elements + +This sample uses `orderby` to sort a list of words alphabetically. + +``` cs --region orderby-syntax --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Orderby using a property + +This sample uses orderby to sort a list of words by length. + +``` cs --region orderby-property --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +## Ordering user defined types + +This sample uses orderby to sort a list of products by name. + +``` cs --region orderby-user-types --source-file ../src/Orderings.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Orderby descending »](./orderings-2.md) Previous: [Partitions with conditions «](./partitions-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/partitions-2.md b/101-linq-samples/docs/partitions-2.md new file mode 100644 index 0000000..d48bb55 --- /dev/null +++ b/101-linq-samples/docs/partitions-2.md @@ -0,0 +1,36 @@ +# LINQ - Partition Operators + +`TakeWhile` and `SkipWhile` *partition* an output sequence based a condition instead of a count of elements. You use these to limit the portion of an input sequence transferred to the output sequence. + +## TakeWhile syntax + +This sample uses `TakeWhile` to return elements starting from the beginning of the array until a number is hit that is not less than 6. + +``` cs --region takewhile-syntax --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Indexed TakeWhile + +This sample uses `TakeWhile` to return elements starting from the beginning of the array until a number is hit that is less than its position in the array. + +``` cs --region indexed-takewhile --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +## SkipWhile syntax + +This sample uses `SkipWhile` to get the elements of the array starting from the first element divisible by 3. + +``` cs --region skipwhile-syntax --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Indexed SkipWhile + +This sample uses `SkipWhile` to get the elements of the array starting from the first element less than its position. + +``` cs --region indexed-skipwhile --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Ordering operations »](./orderings.md) Previous: [Partitions «](./partitions.md)** + +**[Home](../README.md)** + diff --git a/101-linq-samples/docs/partitions.md b/101-linq-samples/docs/partitions.md new file mode 100644 index 0000000..49a055a --- /dev/null +++ b/101-linq-samples/docs/partitions.md @@ -0,0 +1,36 @@ +# LINQ - Partition Operators + +The methods `Take`, `Skip`, `TakeWhile` and `SkipWhile` *partition* an output sequence. You use these to limit the portion of an input sequence transferred to the output sequence. + +## Take elements + +This sample uses `Take` to get only the first 3 elements of the array. + +``` cs --region take-syntax --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Nested Take partitions + +This sample uses `Take` to get the first 3 orders from customers in Washington. + +``` cs --region nested-take --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Skip elements + +This sample uses `Skip` to get all but the first 4 elements of the array. + +``` cs --region skip-syntax --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Nested skip partitions + +This sample uses `Take` to get all but the first 2 orders from customers in Washington. + +``` cs --region nested-skip --source-file ../src/Partitions.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Partitions with conditions »](./partitions-2.md) Previous: [Restrictions with indexes and conditions «](./projections-5.md)** + +**[Home](../README.md)** + diff --git a/101-linq-samples/docs/projections-2.md b/101-linq-samples/docs/projections-2.md new file mode 100644 index 0000000..8ff23c5 --- /dev/null +++ b/101-linq-samples/docs/projections-2.md @@ -0,0 +1,40 @@ +# LINQ - Projection Operators + +The `select` clause of a LINQ query *projects* the output sequence. It transforms each input element into the shape of the output sequence + +## Select anonymous types or tuples + +This sample uses `select` to produce a sequence of the uppercase and lowercase versions of each word in the original array. The items in the output sequence are *anonymous types*. That means the compiler generates a class for them with the relevant properties, but that type has a name known only to the compiler. + +``` cs --region select-case-anonymous --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +Beginning with C# 7, you can also project to *tuples*, using the following syntax. The items in the output sequence are instances of `System.ValueTuple`. The compiler adds metadata to provide meaningful member names. + +``` cs --region select-case-tuple --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Use select to create new types + +This sample uses `select` to produce a sequence containing text representations of digits and whether their length is even or odd. + +``` cs --region select-new-type --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +You can choose to create either *anonymous types* or *tuples* in these projections, as shown below: + +``` cs --region select-new-type-tuple --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +You'll likely see many samples in documentation and articles using anonymous types, because those have been available since C# 3.0. However, the new *tuples* projections have some advantages that you can read about on [Microsoft Docs](https://docs.microsoft.com/dotnet/csharp/tuples). All upcoming samples will use the tuples syntax. However, anonymous types also work. + +## Select a subset of properties + +This sample uses `select` to produce a sequence containing some properties of Products, including UnitPrice which is renamed to Price in the resulting type. + +``` cs --region select-subset-properties --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Projection with index and where »](./projections-3.md) Previous: [Projections «](./projections.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/projections-3.md b/101-linq-samples/docs/projections-3.md new file mode 100644 index 0000000..e550c9c --- /dev/null +++ b/101-linq-samples/docs/projections-3.md @@ -0,0 +1,21 @@ +# LINQ - Projection Operators + +The `select` clause of a LINQ query *projects* the output sequence. It transforms each input element into the shape of the output sequence + +## Select with index of item + +This sample uses an indexed `Select` clause to determine if the value of ints in an array match their position in the array. + +``` cs --region select-with-index --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Select combined with where + +This sample combines `select` and `where` to make a simple query that returns the text form of each digit less than 5. + +``` cs --region select-with-where --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Projections from multiple inputs »](./projections-4.md) Previous: [Projects to new types «](./projections-2.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/projections-4.md b/101-linq-samples/docs/projections-4.md new file mode 100644 index 0000000..dc922e0 --- /dev/null +++ b/101-linq-samples/docs/projections-4.md @@ -0,0 +1,29 @@ +# LINQ - Projection Operators + +The `select` clause of a LINQ query *projects* the output sequence. It transforms each input element into the shape of the output sequence + +## Select from multiple input sequences + +This sample uses a compound `from` clause to make a query that returns all pairs of numbers from both arrays such that the number from `numbersA` is less than the number from `numbersB`. + +``` cs --region select-many-syntax --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Select from related input sequences + +This sample uses a compound `from` clause to select all orders where the order total is less than 500.00. + +``` cs --region select-many-drilldown --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Compound select with where clause + +This sample uses a compound `from` clause to select all orders where the order was made in 1998 or later. + +``` cs --region select-many-filter --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Compound projections »](./projections-5.md) Previous: [Restrictions with index and where «](./projections-3.md)** + +**[Home](../README.md)** + diff --git a/101-linq-samples/docs/projections-5.md b/101-linq-samples/docs/projections-5.md new file mode 100644 index 0000000..ef05097 --- /dev/null +++ b/101-linq-samples/docs/projections-5.md @@ -0,0 +1,29 @@ +# LINQ - Projection Operators + +The `select` clause of a LINQ query *projects* the output sequence. It transforms each input element into the shape of the output sequence + +## Compound select with where and assignment + +This sample uses a compound `from` clause to select all orders where the order total is greater than 2000.00 and uses `from` assignment to avoid requesting the total twice. + + +``` cs --region select-many-assignment --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Compound select with multiple where clauses + +This sample uses multiple `from` clauses so that filtering on customers can be done before selecting their orders. This makes the query more efficient by not selecting and then discarding orders for customers outside of Washington. + +``` cs --region multiple-where-clauses --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Compound select with index + +This sample uses an indexed `SelectMany` clause to select all orders, while referring to customers by the order in which they are returned from the query. + +``` cs --region indexed-select-many --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Partition operators »](./partitions.md) Previous: [Restrictions from multiple inputs «](./projections-4.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/projections.md b/101-linq-samples/docs/projections.md new file mode 100644 index 0000000..beb411b --- /dev/null +++ b/101-linq-samples/docs/projections.md @@ -0,0 +1,29 @@ +# LINQ - Projection Operators + +The `select` clause of a LINQ query *projects* the output sequence. It transforms each input element into the shape of the output sequence + +## Select clause + +This sample uses `select` to produce a sequence of ints one higher than those in an existing array of ints. It demonstrates how `select` can modify the input sequence. + +``` cs --region select-syntax --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Select a single property + +This sample uses `select` to return a sequence of just the names of a list of products. + +``` cs --region select-property --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +## Transform with select + +This sample uses `select` to produce a sequence of strings representing the text version of a sequence of ints. + +``` cs --region select-transform --source-file ../src/Projections.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Projections to new types »](./projections-2.md) Previous: [Restrictions «](./restrictions.md)** + +**[Home](../README.md)** + diff --git a/101-linq-samples/docs/quantifiers.md b/101-linq-samples/docs/quantifiers.md new file mode 100644 index 0000000..3e07e1e --- /dev/null +++ b/101-linq-samples/docs/quantifiers.md @@ -0,0 +1,35 @@ +# LINQ - Quantifiers + +The methods `Any`, and `All` determine of all elements or any elements match a condition. + +## Check for any matching elements + +This sample uses `Any` to determine if any of the words in the array contain the substring 'ei'. + +``` cs --region any-matches --source-file ../src/Quantifiers.cs --project ../src/Try101LinqSamples.csproj +``` + +## Group by any elements matching a condition + +This sample uses `Any` to return a grouped a list of products only for categories that have at least one product that is out of stock. + +``` cs --region any-grouped --source-file ../src/Quantifiers.cs --project ../src/Try101LinqSamples.csproj +``` + +## Check that all elements match a condition + +This sample uses `All` to determine whether an array contains only odd numbers. + +``` cs --region all-match --source-file ../src/Quantifiers.cs --project ../src/Try101LinqSamples.csproj +``` + +## Group by all elements matching a condition + +This sample uses `All` to return a grouped a list of products only for categories that have all of their products in stock. + +``` cs --region all-grouped --source-file ../src/Quantifiers.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Aggregate operations »](./aggregates.md) Previous: [Generate sequence elements »](./generators.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/query-execution.md b/101-linq-samples/docs/query-execution.md new file mode 100644 index 0000000..00e9175 --- /dev/null +++ b/101-linq-samples/docs/query-execution.md @@ -0,0 +1,30 @@ +# LINQ - lazy and eager execution + +Learn to specify either eager or lazy query execution. + +## Queries execute lazily + +The following sample shows how query execution is deferred until the query is enumerated at a foreach statement. + +``` cs --region deferred-execution --source-file ../src/QueryExecution.cs --project ../src/Try101LinqSamples.csproj +``` + +## Request eager query execution + +The following sample shows how queries can be executed immediately with operators such as `ToList()`. + +``` cs --region eager-execution --source-file ../src/QueryExecution.cs --project ../src/Try101LinqSamples.csproj +``` + +You can replace the `ToList` call with a `ToArray`. Try it. + +## Reuse queries with new results + +The following sample shows how, because of deferred execution, queries can be used again after data changes and will then operate on the new data. + +``` cs --region reuse-query --source-file ../src/QueryExecution.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Join operators »](./join-operators.md) Previous: [sequence-operations »](./sequence-operations.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/restrictions.md b/101-linq-samples/docs/restrictions.md new file mode 100644 index 0000000..334a946 --- /dev/null +++ b/101-linq-samples/docs/restrictions.md @@ -0,0 +1,42 @@ +# LINQ - Restriction Operators + +The `where` clause of a LINQ query *restricts* the output sequence. Only the elements that match a condition are added to the output sequence. + +## LINQ query structure + +This sample uses where to find all elements of an array less than 5. It demonstrates the components of a query, including a `where` clause that filters for small numbers. + +``` cs --region where-syntax --source-file ../src/Restrictions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Filter elements on a property + +This sample uses where to find all products that are out of stock. Its `where` clause examines a property of the items in the input sequence. + +``` cs --region where-property --source-file ../src/Restrictions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Filter elements on multiple properties + +This sample uses where to find all products that are in stock and cost more than 3.00 per unit. + +``` cs --region where-multiple-properties --source-file ../src/Restrictions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Examine a sequence property of output elements + +This sample uses where to find all customers in Washington and then uses the resulting sequence to drill down into their orders. + +``` cs --region where-drilldown --source-file ../src/Restrictions.cs --project ../src/Try101LinqSamples.csproj +``` + +## Filter elements based on position + +This sample demonstrates an indexed Where clause that returns digits whose name is shorter than their value. + +``` cs --region where-indexed --source-file ../src/Restrictions.cs --project ../src/Try101LinqSamples.csproj +``` + +Notice that this final example shows the `Where` method rather than the `where` clause. The two forms are equivalent. + +**Next: [Projection operators »](./projections.md) Previous: [Home «](../README.md)** diff --git a/101-linq-samples/docs/sequence-operations.md b/101-linq-samples/docs/sequence-operations.md new file mode 100644 index 0000000..1c2f769 --- /dev/null +++ b/101-linq-samples/docs/sequence-operations.md @@ -0,0 +1,43 @@ +# LINQ - Sequence operations + +These operators compare or manipulate entire sequences: `EqualAll`, `Concat`, and `Combine`. + +## Compare two sequences for equality + +This sample uses `EqualAll` to see if two sequences match on all elements in the same order. + +``` cs --region equal-sequence --source-file ../src/SequenceOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +Change the order of elements in one sequence and try that sample again: + +```csharp +var wordsB = new string[] { "apple", "blueberry", "cherry" }; +``` + +Notice that sequences are equal if they contain the same elements, and those elements are in the same order. + +## Concatenate two sequences + +This sample uses `Concat` to create one sequence that contains each array's values, one after the other. + +``` cs --region concat-series --source-file ../src/SequenceOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Concatenate projections from two sequences + +This sample uses `Concat` to create one sequence that contains the names of all customers and products, including any duplicates. + +``` cs --region concat-projections --source-file ../src/SequenceOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Combine sequences with zip + +This sample calculates the dot product of two integer vectors. It uses `Zip` to calculate the dot product, passing it a lambda function to multiply two arrays, element by element, and sum the result. + +``` cs --region dot-product --source-file ../src/SequenceOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Deferred and eager execution »](./query-execution.md) Previous: [Aggregates-Average »](./aggregates-4.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/sets-2.md b/101-linq-samples/docs/sets-2.md new file mode 100644 index 0000000..4ccdd6b --- /dev/null +++ b/101-linq-samples/docs/sets-2.md @@ -0,0 +1,35 @@ +# LINQ - Set Operators + +The methods `Distinct`, `Union`, `Intersect`, and `Except` provide set operations to compare multiple sequences. + +## Find the intersection of two sets + +This sample uses `Intersect` to create one sequence that contains the common values shared by both arrays. + +``` cs --region intersect-syntax --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the intersection of query results + +This sample uses `Intersect` to create one sequence that contains the common first letter from both product and customer names. + +``` cs --region intersect-different-queries --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Difference of two sets + +This sample uses `Except` to create a sequence that contains the values from `numbersA` that are not also in `numbersB`. + +``` cs --region except-syntax --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Difference of two queries + +This sample uses `Except` to create one sequence that contains the first letters of product names that are not also first letters of customer names. + +``` cs --region difference-of-queries --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Conversion operators »](./conversions.md) Previous: [Set operations distinct and union «](./sets.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/docs/sets.md b/101-linq-samples/docs/sets.md new file mode 100644 index 0000000..a58292b --- /dev/null +++ b/101-linq-samples/docs/sets.md @@ -0,0 +1,36 @@ +# LINQ - Set Operators + +The methods `Distinct`, `Union`, `Intersect`, and `Except` provide set operations to compare multiple sequences. + +## Find distinct elements + +This sample uses `Distinct` to remove duplicate elements in a sequence of factors of 300. + +``` cs --region distinct-syntax --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find distinct values of a property + +This sample uses `Distinct` to find the unique Category names. + +``` cs --region distinct-property-values --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Find the union of sets + +This sample uses `Union` to create one sequence that contains the unique values from both arrays. + +``` cs --region union-syntax --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +## Union of query results + +This sample uses `Union` to create one sequence that contains the unique first letter from both product and customer names. It shows how you can combine the results of two different queries that produce the same element type. + + +``` cs --region union-query-results --source-file ../src/SetOperations.cs --project ../src/Try101LinqSamples.csproj +``` + +**Next: [Intersect and except set operations »](./sets-2.md) Previous: [Nested groupings with a custom comparer «](./groupings-3.md)** + +**[Home](../README.md)** diff --git a/101-linq-samples/readme.md b/101-linq-samples/readme.md new file mode 100644 index 0000000..dfc776d --- /dev/null +++ b/101-linq-samples/readme.md @@ -0,0 +1,183 @@ +# 101 LINQ Samples +![dotnet try Enabled](https://img.shields.io/badge/Try_.NET-Enabled-501078.svg) + +

+ +

+ +Learn how to use LINQ in your applications with these code samples, covering the entire range of LINQ functionality, demonstrating LINQ with objects. Once you've learned LINQ using object sequences, you can use LINQ with any supported data source. + +## Exploring LINQ using this tutorial + +This tutorial starts with the [fundamentals of LINQ](docs/restrictions.md). You can follow each page in order to explore all the elements of LINQ. Following step-by-step lets you explore LINQ from these fundamental queries through more complicated queries, up to the most complex uses. + +Alternatively, if you're familiar with LINQ, you can jump to a specific section to refresh your knowledge, or learn new techniques. Here is the full list of samples: + +### [Restriction operators](docs/restrictions.md): The `where` keyword + +The `where` keyword or `Where` method provide this capability. These operators restrict, or filter, the input sequence to produce an output sequence. + +- [Your first query](docs/restrictions.md#linq-query-structure): the structure of a LINQ query. +- [Filter elements on a property](docs/restrictions.md#filter-elements-on-a-property): filter elements based on a single property +- [Filter elements using multiple properties](docs/restrictions.md#filter-elements-on-multiple-properties): test multiple properties to filter elements in a sequence. +- [Filter and drilldown into the output elements](docs/restrictions.md#examine-a-sequence-property-of-output-elements): filter input elements, then drill into a sequence on each output element. +- [Filter input elements based on index](docs/restrictions.md#filter-elements-based-on-position): use an element's position to filter it. + +### [Projection operators](docs/projections.md): The `select` keyword + +The `select` keyword or `Select` method provide this capability. These operators create output sequence elements from input sequence elements. The output elements may be either the same or different types. + +- [Select clause](docs/projections.md#select-clause): Select clause structure +- [Select one property the input elements](docs/projections.md#select-a-single-property): Select a single property from an input element. +- [Transform to an element of another sequence](docs/projections.md#transform-with-select): Map an input sequence element to an output sequence element. +- [Select anonymous types or tuples](docs/projections-2.md#select-anonymous-types-or-tuples): Select output elements that are anonymous types or tuples. +- [Create new types with select](docs/projections-2.md#use-select-to-create-new-types): Construct new properties for output elements. +- [Select a subset of properties into a new type](docs/projections-2.md#select-a-subset-of-properties): Trip the data selected for output elements. +- [Select the index of source item](docs/projections-3.md#select-with-index-of-item): Include an elements position as part of the projection. +- [Combine select and where](docs/projections-3.md#select-combined-with-where): Filter output elements before selecting properties. +- [Combine multiple input sequences](docs/projections-4.md#select-from-multiple-input-sequences): Combine every element of the first sequence with each element of a second input sequence. +- [Select from related input sequences](docs/projections-4.md#select-from-related-input-sequences): Filter on a property of a nested sequence. +- [Select multiple sequences with filters](docs/projections-4.md#compound-select-with-where-clause): Filter on properties of several related input sequences. +- [Select from related sequences ](docs/projections-5.md#compound-select-with-where-and-assignment): Cache a nested sequence to select properties from it. +- [Select many with multiple filters](docs/projections-5.md#compound-select-with-multiple-where-clauses): Filter elements on multiple input sequences. +- [Select many with element index](docs/projections-5.md#compound-select-with-index): Select the index of an input element along with other properties of the element. + +## [Partition operators](docs/partitions.md) + +Use the `Take`, `Skip`, `TakeWhile` and `SkipWhile` methods to partition the input sequence. You can get a slice of the input sequence as the output sequence. + +- [Take the first elements](docs/partitions.md#take-elements): Take no more than a number of elements. +- [Take from nested results](docs/partitions.md#nested-take-partitions): Query nested sources and take a set of results. +- [Skip the first elements](docs/partitions.md#skip-elements): Start enumerating after a set of elements. +- [Skip from nested results](docs/partitions.md#nested-skip-partitions): Query nested sources and skip the first results +- [Take based on a condition](docs/partitions-2.md#takewhile-syntax): Take elements while a condition is true.. +- [Indexed TakeWhile method](docs/partitions-2.md#indexed-takewhile): Take based on a condition and the index of an element. +- [Skip based on a condition](docs/partitions-2.md#skipwhile-syntax): Skip elements as long as a condition is true. +- [Indexed SkipWhile method](docs/partitions-2.md#indexed-skipwhile): Skip based on a condition and the index of an element. + +## [Ordering operators](docs/orderings.md) + +The `orderby` keyword, along with `descending`, and the `OrderBy`, `ThenBy`, `OrderbyDescending` and `ThenByDescending` LINQ queries are used to sort data output. + +- [Sort elements](docs/orderings.md#orderby-sorts-elements): Sort elements using the standard sort order. +- [Orderby using a single property](docs/orderings.md#orderby-property): You can sort elements on a single property value +- [Order types you've defined](docs/orderings.md#ordering-user-defined-types): You can use any property that has an ordering relation to order types you've created. +- [Sort in descending order](docs/orderings-2.md#orderby-descending): Add `descending` to sort in descending order +- [Orderby descending on types you define](docs/orderings-2.md#descending-ordering-user-defined-types): With a defined sort order, you can sort in descending order. +- [Thenby to define a secondary sort](docs/orderings-3.md#orderby-multiple-properties): You can define secondary sorts when the primary sort keys are equal. +- [Thenby descending](docs/orderings-3.md#multiple-ordering-descending): Try multiple sort orders in descending order. +- [Reverse the input sequence](docs/orderings-3.md#reverse-the-sequence): The `Reverse` method reverses an input sequence. +- [Orderby with a custom compare function](docs/orderings-4.md#ordering-with-a-custom-comparer): You can define a custom compare function to sort elements. +- [Orderby descending with a custom compare function](docs/orderings-4.md#descending-orders-with-a-custom-comparer): Descending sort can use a custom comparer. +- [Thenby using a comparer](docs/orderings-5.md#multiple-ordering-with-a-custom-comparer): You can mix a standard sort order with a custom comparer. +- [Thenby descending using a comparer](docs/orderings-5.md#multiple-descending-order-with-a-custom-comparer): You can also sort in descending order. + +## [Grouping operators](docs/groupings.md) + +The `GroupBy` and `into` operators organize a sequence into buckets. + +- [Group by into buckets](docs/groupings.md#group-by-into-buckets): Group items into buckets based on a property. +- [Group by using a property](docs/groupings.md#groupby-using-a-property): Group items based on a property of the input sequence. +- [Group by using a key property](docs/groupings.md#grouping-using-a-key-property): Group items based on a key value. +- [Nested group by queries](docs/groupings.md#nested-group-by-queries): Nest groups of buckets into a tree structure. +- [Group by using a custom comparer](docs/groupings-2.md): Group items based on a custom function. +- [Nested group by using a custom comparer](docs/groupings-3.md): Build a nested tree structure based on a custom comparer. + +## [Set Operators](docs/sets.md) + +These operators provide functionality to compare multiple sets of data. You can find the intersection, union, all distinct elements and the difference between sets. + +- [Find distinct elements](docs/sets.md#find-distinct-elements): Build a set of the distinct elements in two sets. +- [Find all distinct values of a single property](docs/sets.md#find-distinct-values-of-a-property): Build a combined set based on values of a single property. +- [Find the union of sets](docs/sets.md#find-the-union-of-sets): Build a set that is the union of two sets. +- [Union of query results](docs/sets.md#union-of-query-results): Find the union of two query results. +- [Find the intersection of sets](docs/sets-2.md#find-the-intersection-of-two-sets): Produce a set that is the intersection of two sets. +- [Find the intersection of query results](docs/sets-2.md#find-the-intersection-of-query-results): Build the intersection of two query result sets. +- [Find the difference of two sets using except](docs/sets-2.md#find-the-difference-of-two-sets): Find elements in the first set that aren't present in the section set. +- [Find the difference of two queries using except](docs/sets-2.md#difference-of-two-queries): Find elements in the first result set that are not present in the second result set. + +## [Conversion operators](docs/conversions.md) + +Sometimes you want to convert a query result set to a different kind of collection. These operators show how you can do this. + +- [Convert results to an Array](docs/conversions.md#convert-to-array): Convert an output sequence to an `Array`. +- [Convert results to a list](docs/conversions.md#convert-to-list): Convert an output sequence to a `List`. +- [Convert results to a dictionary](docs/conversions.md#convert-to-dictionary): Convert the results of a query to a `Dictionary` based on a property of the output sequence elements. +- [Convert results based on item type](docs/conversions.md#convert-elements-that-match-a-type): Produce an output sequence of only those input elements that match a given type. + +## [Element operators](docs/elements.md) + +The methods `First`, `FirstOrDefault`, `Last`, `LastOrDefault`, and `ElementAt` retrieve elements based on the position of that element in the sequence. + +- [Retrieve the first element](docs/elements.md#find-the-first-element): This examples assumes the sequence has at least one element. +- [Retrieve the first matching element](docs/elements.md#find-the-first-matching-element): Find the first element that matches a condition. At least one matching element must exist. +- [Retrieve the first element or default](docs/elements.md#first-element-of-a-possibly-empty-sequence): Find the first element, or `null`, if the sequence is empty. +- [Retrieve the first matching element or default](docs/elements.md#first-matching-element-or-default): Retrieve the first matching element, or null. +- [Find an element by position](docs/elements.md#find-element-at-position): Retrieve the element at a certain position. + +## [Generate sequences](docs/generators.md) + +These methods generate sequences of integers. + +- [Generate a range of numbers](docs/generators.md#create-a-range-of-numbers): Generate sequential numbers. +- [Repeat the same number](docs/generators.md#repeat-the-same-number): Generate the samve value for each element. + +## [Quantifying members](docs/quantifiers.md) + +The methods `Any` and `All` test for elements that match a condition. `Any` checks for one element. `All` checks that all elements match the condition. + +- [Check if any elements match a condition](docs/quantifiers.md#check-for-any-matching-elements): Does at least one element match a condition? +- [Group elements that match a condition](docs/quantifiers.md#group-by-any-elements-matching-a-condition): Group elements by those that match a conition. +- [Check if all elements match a condition](docs/quantifiers.md#check-that-all-matching-elements): Do all elements match a condition? +- [Group where all elements match a condition](docs/quantifiers.md#group-by-all-elements-matching-a-condition): Group all elements that match a given condition. + +## [Aggregator operators](docs/aggregates.md) + +There are a number of methods that perform calculations on values in a sequence. Note that some of these methods require that the input sequence is a numeric type. Those methods are noted below. + +- [Count all elements in a sequence](docs/aggregates.md#count-all-elements-in-a-sequence): Count all elements works on any type. +- [Count all elements matching a condition in a sequence](docs/aggregates.md#count-all-elements-matching-a-condition): Count all elements that match a conditin. +- [Count all elements from a nested query](docs/aggregates.md#count-all-elements-nested-in-a-query): Count all elements in a nested query result. +- [Count all elements in a group](docs/aggregates.md#count-all-elements-that-are-members-of-a-group): Count all the elements in a group. +- [Sum all elements in a sequence](docs/aggregates-1.md#sum-all-numeric-elements-in-a-sequence): Sum all elements in a sequence of numbers. +- [Sum a projection from sequence](docs/aggregates-1.md#sum-a-projection-from-a-sequence): Sum a numeric projection from a sequence of elements. +- [Sum all elements in a group](docs/aggregates-1.md#sum-all-elements-that-are-members-of-a-group): Sum the numeric elements in a group projection. +- [Find the minimum element in a sequence](docs/aggregates-2.md#find-the-minimum-of-a-sequence-of-elements): Find the minimum value in a numeric sequence. +- [Find the minimum of a projection from a sequence](docs/aggregates-2.md#find-the-minimum-of-a-projection): Find the minimum value of a numeric projection from a sequence. +- [Find the minimum in each group](docs/aggregates-2.md#find-the-minimum-in-each-group): Find the smallest numeric value in a group projection. +- [Find all minimums in a group](docs/aggregates-2.md#find-all-elements-matching-the-minimum): Find all elements that are the minimum numeric value. +- [Find the maximum element in a sequence](docs/aggregates-3.md#find-the-maximum-of-a-sequence-of-elements): Find the maximum of a numeric sequence. +- [Find the maximum of a projection from a sequence](docs/aggregates-3.md#find-the-maximum-of-a-projection): Find the maximum of a numeric projection of a sequence. +- [Find the maximum in each group](docs/aggregates-3.md#find-the-maximum-in-each-group): Find the maximum numeric value in each output group of a query. +- [Find all maximums in a group](docs/aggregates-3.md#find-all-elements-matching-the-maximum): Find all numeric values that match the maximum value. +- [Find the average of all element in a sequence](docs/aggregates-3.md#find-the-average-of-a-sequence-of-elements): Find the average of all numeric values in a sequence. +- [Find the maximum of a projection from a sequence](docs/aggregates-3.md#find-the-average-of-a-projection): Find the maximum of a numeric projection from a sequence. +- [Find the maximum in each group](docs/aggregates-3.md#find-the-average-in-each-group): Find the numeric maximum in each group projection. +- [Compute an aggregate from all elements in a sequence](docs/aggregates-4.md#compute-an-aggregate-value-from-all-elements-of-a-sequence): Compute a single value from all elements in a sequence. These need not be numeric sequences. +- [Compute an aggregate from a seed and elements in a sequence](docs/aggregates-4.md#compute-an-aggregate-value-from-a-seed-value-and-all-elements-of-a-sequence): Compute a single value from a seed value and a sequence. The elements need not be numeric. + +## [Sequence operations](docs/sequence-operations.md) + +These methods operate on entire sequences rather than elements of a sequence. They compare sequences or create new sequences from combining all elements. + +- [Compare two sequences for equality](docs/sequence-operations.md#count-all-elements-in-a-sequence): Do two sequences contain the same elements in the same order? +- [Concatenate two sequences](docs/sequence-operations.md#concatenate-projections-from-two-sequences): Create a new sequence from all elements in two source sequences. +- [Concatenate projections from two sequences](docs/sequence-operations.md#concatenate-projections-from-two-sequences): Create a new sequence from a projection of all elements in two source collections. +- [Combine sequences with zip](docs/sequence-operations.md#combine-sequences-with-zip): Combine two sequences by producing a new elements from pairs of elements in two source sequences. + +## [Eager and lazy query execution](docs/query-execution.md) + +You can use different query operations to specify eager execution instead of lazy execution. + +- [Queries execute lazily](docs/query-execution.md#queries-execute-lazily): This demonstrates the default query execution. +- [Request eager execution](docs/query-execution.md#request-eager-query-execution): This forces eager execution to demonstrate teh difference. +- [Reuse queries with new results](docs/query-execution.md#reuse-queries-with-new-results): Queries executing lazily can produce different results if the source collection changes. + +## [Join operations](docs/join-operators.md) + +These operations perform similar functions to SQL join operators. These work with any LINQ data source. + +- [Cross join](docs/join-operators.md#cross-join): Perform a cross join. +- [Group join](docs/join-operators.md#group-join): Perform a group join. +- [Cross join with group join](docs/join-operators.md#cross-join-with-group-join): Perform a cross join combined with a group join. +- [Left outer join](docs/join-operators.md#left-outer-join-using-group-join): Simulate a left outer join using a group join. diff --git a/101-linq-samples/src/AggregateOperators.cs b/101-linq-samples/src/AggregateOperators.cs new file mode 100644 index 0000000..1028b53 --- /dev/null +++ b/101-linq-samples/src/AggregateOperators.cs @@ -0,0 +1,307 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class AggregateOperators + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int CountSyntax() + { + #region count-syntax + int[] factorsOf300 = { 2, 2, 3, 5, 5 }; + + int uniqueFactors = factorsOf300.Distinct().Count(); + + Console.WriteLine($"There are {uniqueFactors} unique factors of 300."); + #endregion + return 0; + } + + public int CountConditional() + { + #region count-conditional + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + int oddNumbers = numbers.Count(n => n % 2 == 1); + + Console.WriteLine("There are {0} odd numbers in the list.", oddNumbers); + #endregion + return 0; + } + + public int NestedCount() + { + #region nested-count + List customers = GetCustomerList(); + + var orderCounts = from c in customers + select (c.CustomerID, OrderCount: c.Orders.Count()); + + foreach(var customer in orderCounts) + { + Console.WriteLine($"ID: {customer.CustomerID}, count: {customer.OrderCount}"); + } + + #endregion + return 0; + } + + public int GroupedCount() + { + #region grouped-count + List products = GetProductList(); + + var categoryCounts = from p in products + group p by p.Category into g + select (Category: g.Key, ProductCount: g.Count()); + + foreach(var c in categoryCounts) + { + Console.WriteLine($"Category: {c.Category}: Product count: {c.ProductCount}"); + } + #endregion + return 0; + } + + public int SumSyntax() + { + #region sum-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + double numSum = numbers.Sum(); + + Console.WriteLine($"The sum of the numbers is {numSum}"); + #endregion + return 0; + } + + public int SumProjection() + { + #region sum-of-projection + string[] words = { "cherry", "apple", "blueberry" }; + + double totalChars = words.Sum(w => w.Length); + + Console.WriteLine($"There are a total of {totalChars} characters in these words."); + #endregion + return 0; + } + + public int SumGrouped() + { + #region grouped-sum + List products = GetProductList(); + + var categories = from p in products + group p by p.Category into g + select (Category: g.Key, TotalUnitsInStock: g.Sum(p => p.UnitsInStock)); + + foreach(var pair in categories) + { + Console.WriteLine($"Category: {pair.Category}, Units in stock: {pair.TotalUnitsInStock}"); + } + #endregion + return 0; + } + + public int MinSyntax() + { + #region min-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + int minNum = numbers.Min(); + + Console.WriteLine($"The minimum number is {minNum}"); + #endregion + return 0; + } + + public int MinProjection() + { + #region min-projection + string[] words = { "cherry", "apple", "blueberry" }; + + int shortestWord = words.Min(w => w.Length); + + Console.WriteLine($"The shortest word is {shortestWord} characters long."); + #endregion + return 0; + } + + public int MinGrouped() + { + #region min-grouped + List products = GetProductList(); + + var categories = from p in products + group p by p.Category into g + select (Category: g.Key, CheapestPrice: g.Min(p => p.UnitPrice)); + + foreach(var c in categories) + { + Console.WriteLine($"Category: {c.Category}, Lowest price: {c.CheapestPrice}"); + } + #endregion + return 0; + } + + public int MinEachGroup() + { + #region min-each-group + List products = GetProductList(); + + var categories = from p in products + group p by p.Category into g + let minPrice = g.Min(p => p.UnitPrice) + select (Category: g.Key, CheapestProducts: g.Where(p => p.UnitPrice == minPrice)); + + foreach (var c in categories) + { + Console.WriteLine($"Category: {c.Category}"); + foreach(var p in c.CheapestProducts) + { + Console.WriteLine($"\tProduct: {p}"); + } + } + #endregion + return 0; + } + + public int MaxSyntax() + { + #region max-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + int maxNum = numbers.Max(); + + Console.WriteLine($"The maximum number is {maxNum}"); + #endregion + return 0; + } + + public int MaxProjection() + { + #region max-projection + string[] words = { "cherry", "apple", "blueberry" }; + + int longestLength = words.Max(w => w.Length); + + Console.WriteLine($"The longest word is {longestLength} characters long."); + #endregion + return 0; + } + + public int MaxGrouped() + { + #region max-grouped + List products = GetProductList(); + + var categories = from p in products + group p by p.Category into g + select (Category: g.Key, MostExpensivePrice: g.Max(p => p.UnitPrice)); + + foreach (var c in categories) + { + Console.WriteLine($"Category: {c.Category} Most expensive product: {c.MostExpensivePrice}"); + } + #endregion + return 0; + } + + public int MaxEachGroup() + { + #region max-each-group + List products = GetProductList(); + + var categories = from p in products + group p by p.Category into g + let maxPrice = g.Max(p => p.UnitPrice) + select (Category: g.Key, MostExpensiveProducts: g.Where(p => p.UnitPrice == maxPrice)); + + foreach (var c in categories) + { + Console.WriteLine($"Category: {c.Category}"); + foreach (var p in c.MostExpensiveProducts) + { + Console.WriteLine($"\t{p}"); + } + } + #endregion + return 0; + } + + public int AverageSyntax() + { + #region average-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + double averageNum = numbers.Average(); + + Console.WriteLine($"The average number is {averageNum}."); + #endregion + return 0; + } + + public int AverageProjection() + { + #region average-projection + string[] words = { "cherry", "apple", "blueberry" }; + + double averageLength = words.Average(w => w.Length); + + Console.WriteLine($"The average word length is {averageLength} characters."); + #endregion + return 0; + } + + public int AverageGrouped() + { + #region average-grouped + List products = GetProductList(); + + var categories = from p in products + group p by p.Category into g + select (Category: g.Key, AveragePrice: g.Average(p => p.UnitPrice)); + + foreach (var c in categories) + { + Console.WriteLine($"Category: {c.Category}, Average price: {c.AveragePrice}"); + } + #endregion + return 0; + } + + public int AggregateSyntax() + { + #region aggregate-syntax + double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 }; + + double product = doubles.Aggregate((runningProduct, nextFactor) => runningProduct * nextFactor); + + Console.WriteLine($"Total product of all numbers: {product}"); + #endregion + return 0; + } + + public int SeededAggregate() + { + #region aggregate-seeded + double startBalance = 100.0; + + int[] attemptedWithdrawals = { 20, 10, 40, 50, 10, 70, 30 }; + + double endBalance = + attemptedWithdrawals.Aggregate(startBalance, + (balance, nextWithdrawal) => + ((nextWithdrawal <= balance) ? (balance - nextWithdrawal) : balance)); + + Console.WriteLine($"Ending balance: {endBalance}"); + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/Conversions.cs b/101-linq-samples/src/Conversions.cs new file mode 100644 index 0000000..e1b3e30 --- /dev/null +++ b/101-linq-samples/src/Conversions.cs @@ -0,0 +1,77 @@ +using System; +using System.Linq; + +namespace Try101LinqSamples +{ + public class Conversions + { + public int ConvertToArray() + { + #region convert-to-array + double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 }; + + var sortedDoubles = from d in doubles + orderby d descending + select d; + var doublesArray = sortedDoubles.ToArray(); + + Console.WriteLine("Every other double from highest to lowest:"); + for (int d = 0; d < doublesArray.Length; d += 2) + { + Console.WriteLine(doublesArray[d]); + } + #endregion + return 0; + } + + public int ConvertToList() + { + #region convert-to-list + string[] words = { "cherry", "apple", "blueberry" }; + + var sortedWords = from w in words + orderby w + select w; + var wordList = sortedWords.ToList(); + + Console.WriteLine("The sorted word list:"); + foreach (var w in wordList) + { + Console.WriteLine(w); + } + #endregion + return 0; + } + + public int ConvertToDictionary() + { + #region convert-to-dictionary + var scoreRecords = new[] { new {Name = "Alice", Score = 50}, + new {Name = "Bob" , Score = 40}, + new {Name = "Cathy", Score = 45} + }; + + var scoreRecordsDict = scoreRecords.ToDictionary(sr => sr.Name); + + Console.WriteLine("Bob's score: {0}", scoreRecordsDict["Bob"]); + #endregion + return 0; + } + + public int ConvertSelectedItems() + { + #region convert-to-type + object[] numbers = { null, 1.0, "two", 3, "four", 5, "six", 7.0 }; + + var doubles = numbers.OfType(); + + Console.WriteLine("Numbers stored as doubles:"); + foreach (var d in doubles) + { + Console.WriteLine(d); + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/DataSources/Customers.cs b/101-linq-samples/src/DataSources/Customers.cs new file mode 100644 index 0000000..87e7318 --- /dev/null +++ b/101-linq-samples/src/DataSources/Customers.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace Try101LinqSamples +{ + public class Customer + { + public string CustomerID { get; set; } + public string CompanyName { get; set; } + public string Address { get; set; } + public string City { get; set; } + public string Region { get; set; } + public string PostalCode { get; set; } + public string Country { get; set; } + public string Phone { get; set; } + public Order[] Orders { get; set; } + public override string ToString() => + $"{CustomerID} {CompanyName}\n{Address}\n{City}, {Region} {PostalCode} {Country}\n{Phone}"; + } + + public class Order + { + public int OrderID { get; set; } + public DateTime OrderDate { get; set; } + public decimal Total { get; set; } + public override string ToString() => $"{OrderID}: {OrderDate:d} for {Total:C2}"; + } + + public static class Customers + { + public static List CustomerList { get; } = + (from e in XDocument.Parse(InputValues.CustomersXml).Root.Elements("customer") + select new Customer + { + CustomerID = (string)e.Element("id"), + CompanyName = (string)e.Element("name"), + Address = (string)e.Element("address"), + City = (string)e.Element("city"), + Region = (string)e.Element("region"), + PostalCode = (string)e.Element("postalcode"), + Country = (string)e.Element("country"), + Phone = (string)e.Element("phone"), + Orders = ( + from o in e.Elements("orders").Elements("order") + select new Order + { + OrderID = (int)o.Element("id"), + OrderDate = (DateTime)o.Element("orderdate"), + Total = (decimal)o.Element("total") + }).ToArray() + }).ToList(); + } +} diff --git a/101-linq-samples/src/DataSources/InputValues.cs b/101-linq-samples/src/DataSources/InputValues.cs new file mode 100644 index 0000000..c2c7817 --- /dev/null +++ b/101-linq-samples/src/DataSources/InputValues.cs @@ -0,0 +1,5190 @@ +namespace Try101LinqSamples +{ + public static class InputValues + { + // You don't really want to see this. + public const string CustomersXml = +@" + + + ALFKI + Alfreds Futterkiste +
Obere Str. 57
+ Berlin + 12209 + Germany + 030-0074321 + + + 10643 + 1997-08-25T00:00:00 + 814.50 + + + 10692 + 1997-10-03T00:00:00 + 878.00 + + + 10702 + 1997-10-13T00:00:00 + 330.00 + + + 10835 + 1998-01-15T00:00:00 + 845.80 + + + 10952 + 1998-03-16T00:00:00 + 471.20 + + + 11011 + 1998-04-09T00:00:00 + 933.50 + + +
+ + ANATR + Ana Trujillo Emparedados y helados +
Avda.de la Constitución 2222
+ México D.F. + 05021 + Mexico + (5) 555-4729 + + + 10308 + 1996-09-18T00:00:00 + 88.80 + + + 10625 + 1997-08-08T00:00:00 + 479.75 + + + 10759 + 1997-11-28T00:00:00 + 320.00 + + + 10926 + 1998-03-04T00:00:00 + 514.40 + + +
+ + ANTON + Antonio Moreno Taquería +
Mataderos 2312
+ México D.F. + 05023 + Mexico + (5) 555-3932 + + + 10365 + 1996-11-27T00:00:00 + 403.20 + + + 10507 + 1997-04-15T00:00:00 + 749.06 + + + 10535 + 1997-05-13T00:00:00 + 1940.85 + + + 10573 + 1997-06-19T00:00:00 + 2082.00 + + + 10677 + 1997-09-22T00:00:00 + 813.36 + + + 10682 + 1997-09-25T00:00:00 + 375.50 + + + 10856 + 1998-01-28T00:00:00 + 660.00 + + +
+ + AROUT + Around the Horn +
120 Hanover Sq.
+ London + WA1 1DP + UK + (171) 555-7788 + + + 10355 + 1996-11-15T00:00:00 + 480.00 + + + 10383 + 1996-12-16T00:00:00 + 899.00 + + + 10453 + 1997-02-21T00:00:00 + 407.70 + + + 10558 + 1997-06-04T00:00:00 + 2142.90 + + + 10707 + 1997-10-16T00:00:00 + 1641.00 + + + 10741 + 1997-11-14T00:00:00 + 228.00 + + + 10743 + 1997-11-17T00:00:00 + 319.20 + + + 10768 + 1997-12-08T00:00:00 + 1477.00 + + + 10793 + 1997-12-24T00:00:00 + 191.10 + + + 10864 + 1998-02-02T00:00:00 + 282.00 + + + 10920 + 1998-03-03T00:00:00 + 390.00 + + + 10953 + 1998-03-16T00:00:00 + 4441.25 + + + 11016 + 1998-04-10T00:00:00 + 491.50 + + +
+ + BERGS + Berglunds snabbköp +
Berguvsvägen 8
+ Luleå + S-958 22 + Sweden + 0921-12 34 65 + + + 10278 + 1996-08-12T00:00:00 + 1488.80 + + + 10280 + 1996-08-14T00:00:00 + 613.20 + + + 10384 + 1996-12-16T00:00:00 + 2222.40 + + + 10444 + 1997-02-12T00:00:00 + 1031.70 + + + 10445 + 1997-02-13T00:00:00 + 174.90 + + + 10524 + 1997-05-01T00:00:00 + 3192.65 + + + 10572 + 1997-06-18T00:00:00 + 1501.08 + + + 10626 + 1997-08-11T00:00:00 + 1503.60 + + + 10654 + 1997-09-02T00:00:00 + 601.83 + + + 10672 + 1997-09-17T00:00:00 + 3815.25 + + + 10689 + 1997-10-01T00:00:00 + 472.50 + + + 10733 + 1997-11-07T00:00:00 + 1459.00 + + + 10778 + 1997-12-16T00:00:00 + 96.50 + + + 10837 + 1998-01-16T00:00:00 + 1064.50 + + + 10857 + 1998-01-28T00:00:00 + 2048.21 + + + 10866 + 1998-02-03T00:00:00 + 1096.20 + + + 10875 + 1998-02-06T00:00:00 + 709.55 + + + 10924 + 1998-03-04T00:00:00 + 1835.70 + + +
+ + BLAUS + Blauer See Delikatessen +
Forsterstr. 57
+ Mannheim + 68306 + Germany + 0621-08460 + + + 10501 + 1997-04-09T00:00:00 + 149.00 + + + 10509 + 1997-04-17T00:00:00 + 136.80 + + + 10582 + 1997-06-27T00:00:00 + 330.00 + + + 10614 + 1997-07-29T00:00:00 + 464.00 + + + 10853 + 1998-01-27T00:00:00 + 625.00 + + + 10956 + 1998-03-17T00:00:00 + 677.00 + + + 11058 + 1998-04-29T00:00:00 + 858.00 + + +
+ + BLONP + Blondel père et fils +
24, place Kléber
+ Strasbourg + 67000 + France + 88.60.15.31 + + + 10265 + 1996-07-25T00:00:00 + 1176.00 + + + 10297 + 1996-09-04T00:00:00 + 1420.00 + + + 10360 + 1996-11-22T00:00:00 + 7390.20 + + + 10436 + 1997-02-05T00:00:00 + 1994.52 + + + 10449 + 1997-02-18T00:00:00 + 1838.20 + + + 10559 + 1997-06-05T00:00:00 + 520.41 + + + 10566 + 1997-06-12T00:00:00 + 1761.00 + + + 10584 + 1997-06-30T00:00:00 + 593.75 + + + 10628 + 1997-08-12T00:00:00 + 450.00 + + + 10679 + 1997-09-23T00:00:00 + 660.00 + + + 10826 + 1998-01-12T00:00:00 + 730.00 + + +
+ + BOLID + Bólido Comidas preparadas +
C/ Araquil, 67
+ Madrid + 28023 + Spain + (91) 555 22 82 + + + 10326 + 1996-10-10T00:00:00 + 982.00 + + + 10801 + 1997-12-29T00:00:00 + 3026.85 + + + 10970 + 1998-03-24T00:00:00 + 224.00 + + +
+ + BONAP + Bon app' +
12, rue des Bouchers
+ Marseille + 13008 + France + 91.24.45.40 + + + 10331 + 1996-10-16T00:00:00 + 88.50 + + + 10340 + 1996-10-29T00:00:00 + 2436.18 + + + 10362 + 1996-11-25T00:00:00 + 1549.60 + + + 10470 + 1997-03-11T00:00:00 + 1820.80 + + + 10511 + 1997-04-18T00:00:00 + 2550.00 + + + 10525 + 1997-05-02T00:00:00 + 818.40 + + + 10663 + 1997-09-10T00:00:00 + 1930.40 + + + 10715 + 1997-10-23T00:00:00 + 1296.00 + + + 10730 + 1997-11-05T00:00:00 + 484.26 + + + 10732 + 1997-11-06T00:00:00 + 360.00 + + + 10755 + 1997-11-26T00:00:00 + 1948.50 + + + 10827 + 1998-01-12T00:00:00 + 843.00 + + + 10871 + 1998-02-05T00:00:00 + 1979.23 + + + 10876 + 1998-02-09T00:00:00 + 917.00 + + + 10932 + 1998-03-06T00:00:00 + 1788.63 + + + 10940 + 1998-03-11T00:00:00 + 360.00 + + + 11076 + 1998-05-06T00:00:00 + 792.75 + + +
+ + BOTTM + Bottom-Dollar Markets +
23 Tsawassen Blvd.
+ Tsawassen + BC + T2F 8M4 + Canada + (604) 555-4729 + + + 10389 + 1996-12-20T00:00:00 + 1832.80 + + + 10410 + 1997-01-10T00:00:00 + 802.00 + + + 10411 + 1997-01-10T00:00:00 + 966.80 + + + 10431 + 1997-01-30T00:00:00 + 1892.25 + + + 10492 + 1997-04-01T00:00:00 + 851.20 + + + 10742 + 1997-11-14T00:00:00 + 3118.00 + + + 10918 + 1998-03-02T00:00:00 + 1447.50 + + + 10944 + 1998-03-12T00:00:00 + 1025.32 + + + 10949 + 1998-03-13T00:00:00 + 4422.00 + + + 10975 + 1998-03-25T00:00:00 + 717.50 + + + 10982 + 1998-03-27T00:00:00 + 1014.00 + + + 11027 + 1998-04-16T00:00:00 + 877.72 + + + 11045 + 1998-04-23T00:00:00 + 1309.50 + + + 11048 + 1998-04-24T00:00:00 + 525.00 + + +
+ + BSBEV + B's Beverages +
Fauntleroy Circus
+ London + EC2 5NT + UK + (171) 555-1212 + + + 10289 + 1996-08-26T00:00:00 + 479.40 + + + 10471 + 1997-03-11T00:00:00 + 1328.00 + + + 10484 + 1997-03-24T00:00:00 + 386.20 + + + 10538 + 1997-05-15T00:00:00 + 139.80 + + + 10539 + 1997-05-16T00:00:00 + 355.50 + + + 10578 + 1997-06-24T00:00:00 + 477.00 + + + 10599 + 1997-07-15T00:00:00 + 493.00 + + + 10943 + 1998-03-11T00:00:00 + 711.00 + + + 10947 + 1998-03-13T00:00:00 + 220.00 + + + 11023 + 1998-04-14T00:00:00 + 1500.00 + + +
+ + CACTU + Cactus Comidas para llevar +
Cerrito 333
+ Buenos Aires + 1010 + Argentina + (1) 135-5555 + + + 10521 + 1997-04-29T00:00:00 + 225.50 + + + 10782 + 1997-12-17T00:00:00 + 12.50 + + + 10819 + 1998-01-07T00:00:00 + 477.00 + + + 10881 + 1998-02-11T00:00:00 + 150.00 + + + 10937 + 1998-03-10T00:00:00 + 644.80 + + + 11054 + 1998-04-28T00:00:00 + 305.00 + + +
+ + CENTC + Centro comercial Moctezuma +
Sierras de Granada 9993
+ México D.F. + 05022 + Mexico + (5) 555-3392 + + + 10259 + 1996-07-18T00:00:00 + 100.80 + + +
+ + CHOPS + Chop-suey Chinese +
Hauptstr. 29
+ Bern + 3012 + Switzerland + 0452-076545 + + + 10254 + 1996-07-11T00:00:00 + 556.62 + + + 10370 + 1996-12-03T00:00:00 + 1117.60 + + + 10519 + 1997-04-28T00:00:00 + 2314.20 + + + 10731 + 1997-11-06T00:00:00 + 1890.50 + + + 10746 + 1997-11-19T00:00:00 + 2311.70 + + + 10966 + 1998-03-20T00:00:00 + 1098.46 + + + 11029 + 1998-04-16T00:00:00 + 1286.80 + + + 11041 + 1998-04-22T00:00:00 + 1773.00 + + +
+ + COMMI + Comércio Mineiro +
Av.dos Lusíadas, 23
+ São Paulo + SP + 05432-043 + Brazil + (11) 555-7647 + + + 10290 + 1996-08-27T00:00:00 + 2169.00 + + + 10466 + 1997-03-06T00:00:00 + 216.00 + + + 10494 + 1997-04-02T00:00:00 + 912.00 + + + 10969 + 1998-03-23T00:00:00 + 108.00 + + + 11042 + 1998-04-22T00:00:00 + 405.75 + + +
+ + CONSH + Consolidated Holdings +
Berkeley Gardens, 12 Brewery
+ London + WX1 6LT + UK + (171) 555-2282 + + + 10435 + 1997-02-04T00:00:00 + 631.60 + + + 10462 + 1997-03-03T00:00:00 + 156.00 + + + 10848 + 1998-01-23T00:00:00 + 931.50 + + +
+ + DRACD + Drachenblut Delikatessen +
Walserweg 21
+ Aachen + 52066 + Germany + 0241-039123 + + + 10363 + 1996-11-26T00:00:00 + 447.20 + + + 10391 + 1996-12-23T00:00:00 + 86.40 + + + 10797 + 1997-12-25T00:00:00 + 420.00 + + + 10825 + 1998-01-09T00:00:00 + 1030.76 + + + 11036 + 1998-04-20T00:00:00 + 1692.00 + + + 11067 + 1998-05-04T00:00:00 + 86.85 + + +
+ + DUMON + Du monde entier +
67, rue des Cinquante Otages
+ Nantes + 44000 + France + 40.67.88.88 + + + 10311 + 1996-09-20T00:00:00 + 268.80 + + + 10609 + 1997-07-24T00:00:00 + 424.00 + + + 10683 + 1997-09-26T00:00:00 + 63.00 + + + 10890 + 1998-02-16T00:00:00 + 860.10 + + +
+ + EASTC + Eastern Connection +
35 King George
+ London + WX3 6FW + UK + (171) 555-0297 + + + 10364 + 1996-11-26T00:00:00 + 950.00 + + + 10400 + 1997-01-01T00:00:00 + 3063.00 + + + 10532 + 1997-05-09T00:00:00 + 796.35 + + + 10726 + 1997-11-03T00:00:00 + 655.00 + + + 10987 + 1998-03-31T00:00:00 + 2772.00 + + + 11024 + 1998-04-15T00:00:00 + 1966.81 + + + 11047 + 1998-04-24T00:00:00 + 817.88 + + + 11056 + 1998-04-28T00:00:00 + 3740.00 + + +
+ + ERNSH + Ernst Handel +
Kirchgasse 6
+ Graz + 8010 + Austria + 7675-3425 + + + 10258 + 1996-07-17T00:00:00 + 1614.88 + + + 10263 + 1996-07-23T00:00:00 + 1873.80 + + + 10351 + 1996-11-11T00:00:00 + 5398.72 + + + 10368 + 1996-11-29T00:00:00 + 1689.78 + + + 10382 + 1996-12-13T00:00:00 + 2900.00 + + + 10390 + 1996-12-23T00:00:00 + 2090.88 + + + 10402 + 1997-01-02T00:00:00 + 2713.50 + + + 10403 + 1997-01-03T00:00:00 + 855.02 + + + 10430 + 1997-01-30T00:00:00 + 4899.20 + + + 10442 + 1997-02-11T00:00:00 + 1792.00 + + + 10514 + 1997-04-22T00:00:00 + 8623.45 + + + 10571 + 1997-06-17T00:00:00 + 550.59 + + + 10595 + 1997-07-10T00:00:00 + 4725.00 + + + 10633 + 1997-08-15T00:00:00 + 5510.59 + + + 10667 + 1997-09-12T00:00:00 + 1536.80 + + + 10698 + 1997-10-09T00:00:00 + 3436.44 + + + 10764 + 1997-12-03T00:00:00 + 2286.00 + + + 10771 + 1997-12-10T00:00:00 + 344.00 + + + 10773 + 1997-12-11T00:00:00 + 2030.40 + + + 10776 + 1997-12-15T00:00:00 + 6635.28 + + + 10795 + 1997-12-24T00:00:00 + 2158.00 + + + 10836 + 1998-01-16T00:00:00 + 4705.50 + + + 10854 + 1998-01-27T00:00:00 + 2966.50 + + + 10895 + 1998-02-18T00:00:00 + 6379.40 + + + 10968 + 1998-03-23T00:00:00 + 1408.00 + + + 10979 + 1998-03-26T00:00:00 + 4813.50 + + + 10990 + 1998-04-01T00:00:00 + 4288.85 + + + 11008 + 1998-04-08T00:00:00 + 4680.90 + + + 11017 + 1998-04-13T00:00:00 + 6750.00 + + + 11072 + 1998-05-05T00:00:00 + 5218.00 + + +
+ + FAMIA + Familia Arquibaldo +
Rua Orós, 92
+ São Paulo + SP + 05442-030 + Brazil + (11) 555-9857 + + + 10347 + 1996-11-06T00:00:00 + 814.42 + + + 10386 + 1996-12-18T00:00:00 + 166.00 + + + 10414 + 1997-01-14T00:00:00 + 224.83 + + + 10512 + 1997-04-21T00:00:00 + 525.30 + + + 10581 + 1997-06-26T00:00:00 + 310.00 + + + 10650 + 1997-08-29T00:00:00 + 1779.20 + + + 10725 + 1997-10-31T00:00:00 + 287.80 + + +
+ + FISSA + FISSA Fabrica Inter.Salchichas S.A. +
C/ Moralzarzal, 86
+ Madrid + 28034 + Spain + (91) 555 94 44 + +
+ + FOLIG + Folies gourmandes +
184, chaussée de Tournai
+ Lille + 59000 + France + 20.16.10.16 + + + 10408 + 1997-01-08T00:00:00 + 1622.40 + + + 10480 + 1997-03-20T00:00:00 + 756.00 + + + 10634 + 1997-08-15T00:00:00 + 4985.50 + + + 10763 + 1997-12-03T00:00:00 + 616.00 + + + 10789 + 1997-12-22T00:00:00 + 3687.00 + + +
+ + FOLKO + Folk och fä HB +
Åkergatan 24
+ Bräcke + S-844 67 + Sweden + 0695-34 67 21 + + + 10264 + 1996-07-24T00:00:00 + 695.62 + + + 10327 + 1996-10-11T00:00:00 + 1810.00 + + + 10378 + 1996-12-10T00:00:00 + 103.20 + + + 10434 + 1997-02-03T00:00:00 + 321.12 + + + 10460 + 1997-02-28T00:00:00 + 176.10 + + + 10533 + 1997-05-12T00:00:00 + 2222.20 + + + 10561 + 1997-06-06T00:00:00 + 2844.50 + + + 10703 + 1997-10-14T00:00:00 + 2545.00 + + + 10762 + 1997-12-02T00:00:00 + 4337.00 + + + 10774 + 1997-12-11T00:00:00 + 868.75 + + + 10824 + 1998-01-09T00:00:00 + 250.80 + + + 10880 + 1998-02-10T00:00:00 + 1500.00 + + + 10902 + 1998-02-23T00:00:00 + 863.43 + + + 10955 + 1998-03-17T00:00:00 + 74.40 + + + 10977 + 1998-03-26T00:00:00 + 2233.00 + + + 10980 + 1998-03-27T00:00:00 + 248.00 + + + 10993 + 1998-04-01T00:00:00 + 4895.44 + + + 11001 + 1998-04-06T00:00:00 + 2769.00 + + + 11050 + 1998-04-27T00:00:00 + 810.00 + + +
+ + FRANK + Frankenversand +
Berliner Platz 43
+ München + 80805 + Germany + 089-0877310 + + + 10267 + 1996-07-29T00:00:00 + 3536.60 + + + 10337 + 1996-10-24T00:00:00 + 2467.00 + + + 10342 + 1996-10-30T00:00:00 + 1840.64 + + + 10396 + 1996-12-27T00:00:00 + 1903.80 + + + 10488 + 1997-03-27T00:00:00 + 1512.00 + + + 10560 + 1997-06-06T00:00:00 + 1072.42 + + + 10623 + 1997-08-07T00:00:00 + 1336.95 + + + 10653 + 1997-09-02T00:00:00 + 1083.15 + + + 10670 + 1997-09-16T00:00:00 + 2301.75 + + + 10675 + 1997-09-19T00:00:00 + 1423.00 + + + 10717 + 1997-10-24T00:00:00 + 1270.75 + + + 10791 + 1997-12-23T00:00:00 + 1829.76 + + + 10859 + 1998-01-29T00:00:00 + 1078.69 + + + 10929 + 1998-03-05T00:00:00 + 1174.75 + + + 11012 + 1998-04-09T00:00:00 + 2825.30 + + +
+ + FRANR + France restauration +
54, rue Royale
+ Nantes + 44000 + France + 40.32.21.21 + + + 10671 + 1997-09-17T00:00:00 + 920.10 + + + 10860 + 1998-01-29T00:00:00 + 519.00 + + + 10971 + 1998-03-24T00:00:00 + 1733.06 + + +
+ + FRANS + Franchi S.p.A. +
Via Monte Bianco 34
+ Torino + 10100 + Italy + 011-4988260 + + + 10422 + 1997-01-22T00:00:00 + 49.80 + + + 10710 + 1997-10-20T00:00:00 + 93.50 + + + 10753 + 1997-11-25T00:00:00 + 88.00 + + + 10807 + 1997-12-31T00:00:00 + 18.40 + + + 11026 + 1998-04-15T00:00:00 + 1030.00 + + + 11060 + 1998-04-30T00:00:00 + 266.00 + + +
+ + FURIB + Furia Bacalhau e Frutos do Mar +
Jardim das rosas n. 32
+ Lisboa + 1675 + Portugal + (1) 354-2534 + + + 10328 + 1996-10-14T00:00:00 + 1168.00 + + + 10352 + 1996-11-12T00:00:00 + 136.30 + + + 10464 + 1997-03-04T00:00:00 + 1609.28 + + + 10491 + 1997-03-31T00:00:00 + 259.50 + + + 10551 + 1997-05-28T00:00:00 + 1677.30 + + + 10604 + 1997-07-18T00:00:00 + 230.85 + + + 10664 + 1997-09-10T00:00:00 + 1288.39 + + + 10963 + 1998-03-19T00:00:00 + 57.80 + + +
+ + GALED + Galería del gastrónomo +
Rambla de Cataluña, 23
+ Barcelona + 08022 + Spain + (93) 203 4560 + + + 10366 + 1996-11-28T00:00:00 + 136.00 + + + 10426 + 1997-01-27T00:00:00 + 338.20 + + + 10568 + 1997-06-13T00:00:00 + 155.00 + + + 10887 + 1998-02-13T00:00:00 + 70.00 + + + 10928 + 1998-03-05T00:00:00 + 137.50 + + +
+ + GODOS + Godos Cocina Típica +
C/ Romero, 33
+ Sevilla + 41101 + Spain + (95) 555 82 82 + + + 10303 + 1996-09-11T00:00:00 + 1117.80 + + + 10550 + 1997-05-28T00:00:00 + 683.30 + + + 10629 + 1997-08-12T00:00:00 + 2775.05 + + + 10872 + 1998-02-05T00:00:00 + 2058.46 + + + 10874 + 1998-02-06T00:00:00 + 310.00 + + + 10888 + 1998-02-16T00:00:00 + 605.00 + + + 10911 + 1998-02-26T00:00:00 + 858.00 + + + 10948 + 1998-03-13T00:00:00 + 2362.25 + + + 11009 + 1998-04-08T00:00:00 + 616.50 + + + 11037 + 1998-04-21T00:00:00 + 60.00 + + +
+ + GOURL + Gourmet Lanchonetes +
Av.Brasil, 442
+ Campinas + SP + 04876-786 + Brazil + (11) 555-9482 + + + 10423 + 1997-01-23T00:00:00 + 1020.00 + + + 10652 + 1997-09-01T00:00:00 + 318.84 + + + 10685 + 1997-09-29T00:00:00 + 801.10 + + + 10709 + 1997-10-17T00:00:00 + 3424.00 + + + 10734 + 1997-11-07T00:00:00 + 1498.35 + + + 10777 + 1997-12-15T00:00:00 + 224.00 + + + 10790 + 1997-12-22T00:00:00 + 722.50 + + + 10959 + 1998-03-18T00:00:00 + 131.75 + + + 11049 + 1998-04-24T00:00:00 + 273.60 + + +
+ + GREAL + Great Lakes Food Market +
2732 Baker Blvd.
+ Eugene + OR + 97403 + USA + (503) 555-7555 + + + 10528 + 1997-05-06T00:00:00 + 392.20 + + + 10589 + 1997-07-04T00:00:00 + 72.00 + + + 10616 + 1997-07-31T00:00:00 + 4807.00 + + + 10617 + 1997-07-31T00:00:00 + 1402.50 + + + 10656 + 1997-09-04T00:00:00 + 604.22 + + + 10681 + 1997-09-25T00:00:00 + 1287.40 + + + 10816 + 1998-01-06T00:00:00 + 8446.45 + + + 10936 + 1998-03-09T00:00:00 + 456.00 + + + 11006 + 1998-04-07T00:00:00 + 329.68 + + + 11040 + 1998-04-22T00:00:00 + 200.00 + + + 11061 + 1998-04-30T00:00:00 + 510.00 + + +
+ + GROSR + GROSELLA-Restaurante +
5ª Ave.Los Palos Grandes
+ Caracas + DF + 1081 + Venezuela + (2) 283-2951 + + + 10268 + 1996-07-30T00:00:00 + 1101.20 + + + 10785 + 1997-12-18T00:00:00 + 387.50 + + +
+ + HANAR + Hanari Carnes +
Rua do Paço, 67
+ Rio de Janeiro + RJ + 05454-876 + Brazil + (21) 555-0091 + + + 10250 + 1996-07-08T00:00:00 + 1552.60 + + + 10253 + 1996-07-10T00:00:00 + 1444.80 + + + 10541 + 1997-05-19T00:00:00 + 1946.52 + + + 10645 + 1997-08-26T00:00:00 + 1535.00 + + + 10690 + 1997-10-02T00:00:00 + 862.50 + + + 10770 + 1997-12-09T00:00:00 + 236.25 + + + 10783 + 1997-12-18T00:00:00 + 1442.50 + + + 10886 + 1998-02-13T00:00:00 + 3127.50 + + + 10903 + 1998-02-24T00:00:00 + 932.05 + + + 10922 + 1998-03-03T00:00:00 + 742.50 + + + 10925 + 1998-03-04T00:00:00 + 475.15 + + + 10981 + 1998-03-27T00:00:00 + 15810.00 + + + 11022 + 1998-04-14T00:00:00 + 1402.00 + + + 11052 + 1998-04-27T00:00:00 + 1332.00 + + +
+ + HILAA + HILARIÓN-Abastos +
Carrera 22 con Ave.Carlos Soublette #8-35
+ San Cristóbal + Táchira + 5022 + Venezuela + (5) 555-1340 + + + 10257 + 1996-07-16T00:00:00 + 1119.90 + + + 10395 + 1996-12-26T00:00:00 + 2122.92 + + + 10476 + 1997-03-17T00:00:00 + 180.48 + + + 10486 + 1997-03-26T00:00:00 + 1272.00 + + + 10490 + 1997-03-31T00:00:00 + 3163.20 + + + 10498 + 1997-04-07T00:00:00 + 575.00 + + + 10552 + 1997-05-29T00:00:00 + 880.50 + + + 10601 + 1997-07-16T00:00:00 + 2285.00 + + + 10613 + 1997-07-29T00:00:00 + 353.20 + + + 10641 + 1997-08-22T00:00:00 + 2054.00 + + + 10705 + 1997-10-15T00:00:00 + 378.00 + + + 10796 + 1997-12-25T00:00:00 + 2341.36 + + + 10863 + 1998-02-02T00:00:00 + 441.15 + + + 10901 + 1998-02-23T00:00:00 + 934.50 + + + 10957 + 1998-03-18T00:00:00 + 1762.70 + + + 10960 + 1998-03-19T00:00:00 + 265.35 + + + 10976 + 1998-03-25T00:00:00 + 912.00 + + + 11055 + 1998-04-28T00:00:00 + 1727.50 + + +
+ + HUNGC + Hungry Coyote Import Store +
City Center Plaza, 516 Main St.
+ Elgin + OR + 97827 + USA + (503) 555-6874 + + + 10375 + 1996-12-06T00:00:00 + 338.00 + + + 10394 + 1996-12-25T00:00:00 + 442.00 + + + 10415 + 1997-01-15T00:00:00 + 102.40 + + + 10600 + 1997-07-16T00:00:00 + 479.80 + + + 10660 + 1997-09-08T00:00:00 + 1701.00 + + +
+ + HUNGO + Hungry Owl All-Night Grocers +
8 Johnstown Road
+ Cork + Co.Cork + Ireland + 2967 542 + + + 10298 + 1996-09-05T00:00:00 + 2645.00 + + + 10309 + 1996-09-19T00:00:00 + 1762.00 + + + 10335 + 1996-10-22T00:00:00 + 2036.16 + + + 10373 + 1996-12-05T00:00:00 + 1366.40 + + + 10380 + 1996-12-12T00:00:00 + 1313.82 + + + 10429 + 1997-01-29T00:00:00 + 1441.38 + + + 10503 + 1997-04-11T00:00:00 + 2048.50 + + + 10516 + 1997-04-24T00:00:00 + 2381.05 + + + 10567 + 1997-06-12T00:00:00 + 2519.00 + + + 10646 + 1997-08-27T00:00:00 + 1446.00 + + + 10661 + 1997-09-09T00:00:00 + 562.60 + + + 10687 + 1997-09-30T00:00:00 + 4960.90 + + + 10701 + 1997-10-13T00:00:00 + 2864.50 + + + 10712 + 1997-10-21T00:00:00 + 1233.48 + + + 10736 + 1997-11-11T00:00:00 + 997.00 + + + 10897 + 1998-02-19T00:00:00 + 10835.24 + + + 10912 + 1998-02-26T00:00:00 + 6200.55 + + + 10985 + 1998-03-30T00:00:00 + 2023.38 + + + 11063 + 1998-04-30T00:00:00 + 1342.95 + + +
+ + ISLAT + Island Trading +
Garden House, Crowther Way
+ Cowes + Isle of Wight + PO31 7PJ + UK + (198) 555-8888 + + + 10315 + 1996-09-26T00:00:00 + 516.80 + + + 10318 + 1996-10-01T00:00:00 + 240.40 + + + 10321 + 1996-10-03T00:00:00 + 144.00 + + + 10473 + 1997-03-13T00:00:00 + 230.40 + + + 10621 + 1997-08-05T00:00:00 + 758.50 + + + 10674 + 1997-09-18T00:00:00 + 45.00 + + + 10749 + 1997-11-20T00:00:00 + 1080.00 + + + 10798 + 1997-12-26T00:00:00 + 446.60 + + + 10829 + 1998-01-13T00:00:00 + 1764.00 + + + 10933 + 1998-03-06T00:00:00 + 920.60 + + +
+ + KOENE + Königlich Essen +
Maubelstr. 90
+ Brandenburg + 14776 + Germany + 0555-09876 + + + 10323 + 1996-10-07T00:00:00 + 164.40 + + + 10325 + 1996-10-09T00:00:00 + 1497.00 + + + 10456 + 1997-02-25T00:00:00 + 557.60 + + + 10457 + 1997-02-25T00:00:00 + 1584.00 + + + 10468 + 1997-03-07T00:00:00 + 717.60 + + + 10506 + 1997-04-15T00:00:00 + 415.80 + + + 10542 + 1997-05-20T00:00:00 + 469.11 + + + 10630 + 1997-08-13T00:00:00 + 903.60 + + + 10718 + 1997-10-27T00:00:00 + 3463.00 + + + 10799 + 1997-12-26T00:00:00 + 1553.50 + + + 10817 + 1998-01-06T00:00:00 + 10952.84 + + + 10849 + 1998-01-23T00:00:00 + 967.82 + + + 10893 + 1998-02-18T00:00:00 + 5502.11 + + + 11028 + 1998-04-16T00:00:00 + 2160.00 + + +
+ + LACOR + La corne d'abondance +
67, avenue de l'Europe
+ Versailles + 78000 + France + 30.59.84.10 + + + 10858 + 1998-01-29T00:00:00 + 649.00 + + + 10927 + 1998-03-05T00:00:00 + 800.00 + + + 10972 + 1998-03-24T00:00:00 + 251.50 + + + 10973 + 1998-03-24T00:00:00 + 291.55 + + +
+ + LAMAI + La maison d'Asie +
1 rue Alsace-Lorraine
+ Toulouse + 31000 + France + 61.77.61.10 + + + 10350 + 1996-11-11T00:00:00 + 642.06 + + + 10358 + 1996-11-20T00:00:00 + 429.40 + + + 10371 + 1996-12-03T00:00:00 + 72.96 + + + 10413 + 1997-01-14T00:00:00 + 2123.20 + + + 10425 + 1997-01-24T00:00:00 + 360.00 + + + 10454 + 1997-02-21T00:00:00 + 331.20 + + + 10493 + 1997-04-02T00:00:00 + 608.40 + + + 10500 + 1997-04-09T00:00:00 + 523.26 + + + 10610 + 1997-07-25T00:00:00 + 299.25 + + + 10631 + 1997-08-14T00:00:00 + 55.80 + + + 10787 + 1997-12-19T00:00:00 + 2622.76 + + + 10832 + 1998-01-14T00:00:00 + 475.11 + + + 10923 + 1998-03-03T00:00:00 + 748.80 + + + 11051 + 1998-04-27T00:00:00 + 36.00 + + +
+ + LAUGB + Laughing Bacchus Wine Cellars +
1900 Oak St.
+ Vancouver + BC + V3F 2K1 + Canada + (604) 555-3392 + + + 10495 + 1997-04-03T00:00:00 + 278.00 + + + 10620 + 1997-08-05T00:00:00 + 57.50 + + + 10810 + 1998-01-01T00:00:00 + 187.00 + + +
+ + LAZYK + Lazy K Kountry Store +
12 Orchestra Terrace
+ Walla Walla + WA + 99362 + USA + (509) 555-7969 + + + 10482 + 1997-03-21T00:00:00 + 147.00 + + + 10545 + 1997-05-22T00:00:00 + 210.00 + + +
+ + LEHMS + Lehmanns Marktstand +
Magazinweg 7
+ Frankfurt a.M. + 60528 + Germany + 069-0245984 + + + 10279 + 1996-08-13T00:00:00 + 351.00 + + + 10284 + 1996-08-19T00:00:00 + 1170.38 + + + 10343 + 1996-10-31T00:00:00 + 1584.00 + + + 10497 + 1997-04-04T00:00:00 + 1380.60 + + + 10522 + 1997-04-30T00:00:00 + 2318.24 + + + 10534 + 1997-05-12T00:00:00 + 465.70 + + + 10536 + 1997-05-14T00:00:00 + 1645.00 + + + 10557 + 1997-06-03T00:00:00 + 1152.50 + + + 10592 + 1997-07-08T00:00:00 + 516.47 + + + 10593 + 1997-07-09T00:00:00 + 1994.40 + + + 10772 + 1997-12-10T00:00:00 + 3603.22 + + + 10862 + 1998-01-30T00:00:00 + 581.00 + + + 10891 + 1998-02-17T00:00:00 + 368.93 + + + 10934 + 1998-03-09T00:00:00 + 500.00 + + + 11070 + 1998-05-05T00:00:00 + 1629.98 + + +
+ + LETSS + Let's Stop N Shop +
87 Polk St. Suite 5
+ San Francisco + CA + 94117 + USA + (415) 555-5938 + + + 10579 + 1997-06-25T00:00:00 + 317.75 + + + 10719 + 1997-10-27T00:00:00 + 844.25 + + + 10735 + 1997-11-10T00:00:00 + 536.40 + + + 10884 + 1998-02-12T00:00:00 + 1378.07 + + +
+ + LILAS + LILA-Supermercado +
Carrera 52 con Ave.Bolívar #65-98 Llano Largo
+ Barquisimeto + Lara + 3508 + Venezuela + (9) 331-6954 + + + 10283 + 1996-08-16T00:00:00 + 1414.80 + + + 10296 + 1996-09-03T00:00:00 + 1050.60 + + + 10330 + 1996-10-16T00:00:00 + 1649.00 + + + 10357 + 1996-11-19T00:00:00 + 1167.68 + + + 10381 + 1996-12-12T00:00:00 + 112.00 + + + 10461 + 1997-02-28T00:00:00 + 1538.70 + + + 10499 + 1997-04-08T00:00:00 + 1412.00 + + + 10543 + 1997-05-21T00:00:00 + 1504.50 + + + 10780 + 1997-12-16T00:00:00 + 720.00 + + + 10823 + 1998-01-09T00:00:00 + 2826.00 + + + 10899 + 1998-02-20T00:00:00 + 122.40 + + + 10997 + 1998-04-03T00:00:00 + 1885.00 + + + 11065 + 1998-05-01T00:00:00 + 189.42 + + + 11071 + 1998-05-05T00:00:00 + 484.50 + + +
+ + LINOD + LINO-Delicateses +
Ave. 5 de Mayo Porlamar
+ I.de Margarita + Nueva Esparta + 4980 + Venezuela + (8) 34-56-12 + + + 10405 + 1997-01-06T00:00:00 + 400.00 + + + 10485 + 1997-03-25T00:00:00 + 1584.00 + + + 10638 + 1997-08-20T00:00:00 + 2720.05 + + + 10697 + 1997-10-08T00:00:00 + 805.42 + + + 10729 + 1997-11-04T00:00:00 + 1850.00 + + + 10811 + 1998-01-02T00:00:00 + 852.00 + + + 10838 + 1998-01-19T00:00:00 + 1938.38 + + + 10840 + 1998-01-19T00:00:00 + 211.20 + + + 10919 + 1998-03-02T00:00:00 + 1122.80 + + + 10954 + 1998-03-17T00:00:00 + 1659.54 + + + 11014 + 1998-04-10T00:00:00 + 243.18 + + + 11039 + 1998-04-21T00:00:00 + 3090.00 + + +
+ + LONEP + Lonesome Pine Restaurant +
89 Chiaroscuro Rd.
+ Portland + OR + 97219 + USA + (503) 555-9573 + + + 10307 + 1996-09-17T00:00:00 + 424.00 + + + 10317 + 1996-09-30T00:00:00 + 288.00 + + + 10544 + 1997-05-21T00:00:00 + 417.20 + + + 10662 + 1997-09-09T00:00:00 + 125.00 + + + 10665 + 1997-09-11T00:00:00 + 1295.00 + + + 10867 + 1998-02-03T00:00:00 + 98.40 + + + 10883 + 1998-02-12T00:00:00 + 36.00 + + + 11018 + 1998-04-13T00:00:00 + 1575.00 + + +
+ + MAGAA + Magazzini Alimentari Riuniti +
Via Ludovico il Moro 22
+ Bergamo + 24100 + Italy + 035-640230 + + + 10275 + 1996-08-07T00:00:00 + 291.84 + + + 10300 + 1996-09-09T00:00:00 + 608.00 + + + 10404 + 1997-01-03T00:00:00 + 1591.25 + + + 10467 + 1997-03-06T00:00:00 + 235.20 + + + 10635 + 1997-08-18T00:00:00 + 1326.22 + + + 10754 + 1997-11-25T00:00:00 + 55.20 + + + 10784 + 1997-12-18T00:00:00 + 1488.00 + + + 10818 + 1998-01-07T00:00:00 + 833.00 + + + 10939 + 1998-03-10T00:00:00 + 637.50 + + + 10950 + 1998-03-16T00:00:00 + 110.00 + + +
+ + MAISD + Maison Dewey +
Rue Joseph-Bens 532
+ Bruxelles + B-1180 + Belgium + (02) 201 24 67 + + + 10529 + 1997-05-07T00:00:00 + 946.00 + + + 10649 + 1997-08-28T00:00:00 + 1434.00 + + + 10760 + 1997-12-01T00:00:00 + 2917.00 + + + 10892 + 1998-02-17T00:00:00 + 2090.00 + + + 10896 + 1998-02-19T00:00:00 + 750.50 + + + 10978 + 1998-03-26T00:00:00 + 1303.20 + + + 11004 + 1998-04-07T00:00:00 + 295.38 + + +
+ + MEREP + Mère Paillarde +
43 rue St. Laurent
+ Montréal + Québec + H1J 1C3 + Canada + (514) 555-8054 + + + 10332 + 1996-10-17T00:00:00 + 1786.88 + + + 10339 + 1996-10-28T00:00:00 + 3354.00 + + + 10376 + 1996-12-09T00:00:00 + 399.00 + + + 10424 + 1997-01-23T00:00:00 + 9194.56 + + + 10439 + 1997-02-07T00:00:00 + 1078.00 + + + 10505 + 1997-04-14T00:00:00 + 147.90 + + + 10565 + 1997-06-11T00:00:00 + 639.90 + + + 10570 + 1997-06-17T00:00:00 + 2465.25 + + + 10590 + 1997-07-07T00:00:00 + 1101.00 + + + 10605 + 1997-07-21T00:00:00 + 4109.70 + + + 10618 + 1997-08-01T00:00:00 + 2697.50 + + + 10619 + 1997-08-04T00:00:00 + 1260.00 + + + 10724 + 1997-10-30T00:00:00 + 638.50 + + +
+ + MORGK + Morgenstern Gesundkost +
Heerstr. 22
+ Leipzig + 04179 + Germany + 0342-023176 + + + 10277 + 1996-08-09T00:00:00 + 1200.80 + + + 10575 + 1997-06-20T00:00:00 + 2147.40 + + + 10699 + 1997-10-09T00:00:00 + 114.00 + + + 10779 + 1997-12-16T00:00:00 + 1335.00 + + + 10945 + 1998-03-12T00:00:00 + 245.00 + + +
+ + NORTS + North/South +
South House, 300 Queensbridge
+ London + SW7 1RZ + UK + (171) 555-7733 + + + 10517 + 1997-04-24T00:00:00 + 352.00 + + + 10752 + 1997-11-24T00:00:00 + 252.00 + + + 11057 + 1998-04-29T00:00:00 + 45.00 + + +
+ + OCEAN + Océano Atlántico Ltda. +
Ing.Gustavo Moncada 8585, Piso 20-A
+ Buenos Aires + 1010 + Argentina + (1) 135-5333 + + + 10409 + 1997-01-09T00:00:00 + 319.20 + + + 10531 + 1997-05-08T00:00:00 + 110.00 + + + 10898 + 1998-02-20T00:00:00 + 30.00 + + + 10958 + 1998-03-18T00:00:00 + 781.00 + + + 10986 + 1998-03-30T00:00:00 + 2220.00 + + +
+ + OLDWO + Old World Delicatessen +
2743 Bering St.
+ Anchorage + AK + 99508 + USA + (907) 555-7584 + + + 10260 + 1996-07-19T00:00:00 + 1504.65 + + + 10305 + 1996-09-13T00:00:00 + 3741.30 + + + 10338 + 1996-10-25T00:00:00 + 934.50 + + + 10441 + 1997-02-10T00:00:00 + 1755.00 + + + 10594 + 1997-07-09T00:00:00 + 565.50 + + + 10680 + 1997-09-24T00:00:00 + 1261.88 + + + 10706 + 1997-10-16T00:00:00 + 1893.00 + + + 10855 + 1998-01-27T00:00:00 + 2227.89 + + + 10965 + 1998-03-20T00:00:00 + 848.00 + + + 11034 + 1998-04-20T00:00:00 + 539.40 + + +
+ + OTTIK + Ottilies Käseladen +
Mehrheimerstr. 369
+ Köln + 50739 + Germany + 0221-0644327 + + + 10407 + 1997-01-07T00:00:00 + 1194.00 + + + 10508 + 1997-04-16T00:00:00 + 240.00 + + + 10554 + 1997-05-30T00:00:00 + 1728.52 + + + 10580 + 1997-06-26T00:00:00 + 1013.74 + + + 10684 + 1997-09-26T00:00:00 + 1768.00 + + + 10766 + 1997-12-05T00:00:00 + 2310.00 + + + 10833 + 1998-01-15T00:00:00 + 906.93 + + + 10999 + 1998-04-03T00:00:00 + 1197.95 + + + 11020 + 1998-04-14T00:00:00 + 632.40 + + +
+ + PARIS + Paris spécialités +
265, boulevard Charonne
+ Paris + 75012 + France + (1) 42.34.22.66 + +
+ + PERIC + Pericles Comidas clásicas +
Calle Dr.Jorge Cash 321
+ México D.F. + 05033 + Mexico + (5) 552-3745 + + + 10322 + 1996-10-04T00:00:00 + 112.00 + + + 10354 + 1996-11-14T00:00:00 + 568.80 + + + 10474 + 1997-03-13T00:00:00 + 1249.10 + + + 10502 + 1997-04-10T00:00:00 + 816.30 + + + 10995 + 1998-04-02T00:00:00 + 1196.00 + + + 11073 + 1998-05-05T00:00:00 + 300.00 + + +
+ + PICCO + Piccolo und mehr +
Geislweg 14
+ Salzburg + 5020 + Austria + 6562-9722 + + + 10353 + 1996-11-13T00:00:00 + 8593.28 + + + 10392 + 1996-12-24T00:00:00 + 1440.00 + + + 10427 + 1997-01-27T00:00:00 + 651.00 + + + 10489 + 1997-03-28T00:00:00 + 439.20 + + + 10530 + 1997-05-08T00:00:00 + 4180.00 + + + 10597 + 1997-07-11T00:00:00 + 718.08 + + + 10686 + 1997-09-30T00:00:00 + 1404.45 + + + 10747 + 1997-11-19T00:00:00 + 1912.85 + + + 10844 + 1998-01-21T00:00:00 + 735.00 + + + 11053 + 1998-04-27T00:00:00 + 3055.00 + + +
+ + PRINI + Princesa Isabel Vinhos +
Estrada da saúde n. 58
+ Lisboa + 1756 + Portugal + (1) 356-5634 + + + 10336 + 1996-10-23T00:00:00 + 285.12 + + + 10397 + 1996-12-27T00:00:00 + 716.72 + + + 10433 + 1997-02-03T00:00:00 + 851.20 + + + 10477 + 1997-03-17T00:00:00 + 558.00 + + + 10808 + 1998-01-01T00:00:00 + 1411.00 + + + 11007 + 1998-04-08T00:00:00 + 2633.90 + + +
+ + QUEDE + Que Delícia +
Rua da Panificadora, 12
+ Rio de Janeiro + RJ + 02389-673 + Brazil + (21) 555-4252 + + + 10261 + 1996-07-19T00:00:00 + 448.00 + + + 10291 + 1996-08-27T00:00:00 + 497.52 + + + 10379 + 1996-12-11T00:00:00 + 863.28 + + + 10421 + 1997-01-21T00:00:00 + 1194.27 + + + 10587 + 1997-07-02T00:00:00 + 807.38 + + + 10647 + 1997-08-27T00:00:00 + 636.00 + + + 10720 + 1997-10-28T00:00:00 + 550.00 + + + 10794 + 1997-12-24T00:00:00 + 314.76 + + + 10989 + 1998-03-31T00:00:00 + 1353.60 + + +
+ + QUEEN + Queen Cozinha +
Alameda dos Canàrios, 891
+ São Paulo + SP + 05487-020 + Brazil + (11) 555-1189 + + + 10372 + 1996-12-04T00:00:00 + 9210.90 + + + 10406 + 1997-01-07T00:00:00 + 1830.78 + + + 10487 + 1997-03-26T00:00:00 + 889.70 + + + 10637 + 1997-08-19T00:00:00 + 2761.94 + + + 10659 + 1997-09-05T00:00:00 + 1227.02 + + + 10704 + 1997-10-14T00:00:00 + 595.50 + + + 10728 + 1997-11-04T00:00:00 + 1296.75 + + + 10786 + 1997-12-19T00:00:00 + 1531.08 + + + 10868 + 1998-02-04T00:00:00 + 1920.60 + + + 10913 + 1998-02-26T00:00:00 + 768.75 + + + 10914 + 1998-02-27T00:00:00 + 537.50 + + + 10961 + 1998-03-19T00:00:00 + 1119.90 + + + 11068 + 1998-05-04T00:00:00 + 2027.08 + + +
+ + QUICK + QUICK-Stop +
Taucherstraße 10
+ Cunewalde + 01307 + Germany + 0372-035188 + + + 10273 + 1996-08-05T00:00:00 + 2037.28 + + + 10285 + 1996-08-20T00:00:00 + 1743.36 + + + 10286 + 1996-08-21T00:00:00 + 3016.00 + + + 10313 + 1996-09-24T00:00:00 + 182.40 + + + 10345 + 1996-11-04T00:00:00 + 2924.80 + + + 10361 + 1996-11-22T00:00:00 + 2046.24 + + + 10418 + 1997-01-17T00:00:00 + 1814.80 + + + 10451 + 1997-02-19T00:00:00 + 3849.66 + + + 10515 + 1997-04-23T00:00:00 + 9921.30 + + + 10527 + 1997-05-05T00:00:00 + 1503.00 + + + 10540 + 1997-05-19T00:00:00 + 10191.70 + + + 10549 + 1997-05-27T00:00:00 + 3554.28 + + + 10588 + 1997-07-03T00:00:00 + 3120.00 + + + 10658 + 1997-09-05T00:00:00 + 4464.60 + + + 10691 + 1997-10-03T00:00:00 + 10164.80 + + + 10694 + 1997-10-06T00:00:00 + 4825.00 + + + 10721 + 1997-10-29T00:00:00 + 923.88 + + + 10745 + 1997-11-18T00:00:00 + 4529.80 + + + 10765 + 1997-12-04T00:00:00 + 1515.60 + + + 10788 + 1997-12-22T00:00:00 + 731.50 + + + 10845 + 1998-01-21T00:00:00 + 3812.70 + + + 10865 + 1998-02-02T00:00:00 + 16387.50 + + + 10878 + 1998-02-10T00:00:00 + 1539.00 + + + 10938 + 1998-03-10T00:00:00 + 2731.88 + + + 10962 + 1998-03-19T00:00:00 + 3584.00 + + + 10991 + 1998-04-01T00:00:00 + 2296.00 + + + 10996 + 1998-04-02T00:00:00 + 560.00 + + + 11021 + 1998-04-14T00:00:00 + 6306.24 + + +
+ + RANCH + Rancho grande +
Av.del Libertador 900
+ Buenos Aires + 1010 + Argentina + (1) 123-5555 + + + 10448 + 1997-02-17T00:00:00 + 443.40 + + + 10716 + 1997-10-24T00:00:00 + 706.00 + + + 10828 + 1998-01-13T00:00:00 + 932.00 + + + 10916 + 1998-02-27T00:00:00 + 686.70 + + + 11019 + 1998-04-13T00:00:00 + 76.00 + + +
+ + RATTC + Rattlesnake Canyon Grocery +
2817 Milton Dr.
+ Albuquerque + NM + 87110 + USA + (505) 555-5939 + + + 10262 + 1996-07-22T00:00:00 + 584.00 + + + 10272 + 1996-08-02T00:00:00 + 1456.00 + + + 10294 + 1996-08-30T00:00:00 + 1887.60 + + + 10314 + 1996-09-25T00:00:00 + 2094.30 + + + 10316 + 1996-09-27T00:00:00 + 2835.00 + + + 10346 + 1996-11-05T00:00:00 + 1618.88 + + + 10401 + 1997-01-01T00:00:00 + 3868.60 + + + 10479 + 1997-03-19T00:00:00 + 10495.60 + + + 10564 + 1997-06-10T00:00:00 + 1234.05 + + + 10569 + 1997-06-16T00:00:00 + 890.00 + + + 10598 + 1997-07-14T00:00:00 + 2388.50 + + + 10761 + 1997-12-02T00:00:00 + 507.00 + + + 10820 + 1998-01-07T00:00:00 + 1140.00 + + + 10852 + 1998-01-26T00:00:00 + 2984.00 + + + 10889 + 1998-02-16T00:00:00 + 11380.00 + + + 10988 + 1998-03-31T00:00:00 + 3574.80 + + + 11000 + 1998-04-06T00:00:00 + 903.75 + + + 11077 + 1998-05-06T00:00:00 + 1255.72 + + +
+ + REGGC + Reggiani Caseifici +
Strada Provinciale 124
+ Reggio Emilia + 42100 + Italy + 0522-556721 + + + 10288 + 1996-08-23T00:00:00 + 80.10 + + + 10428 + 1997-01-28T00:00:00 + 192.00 + + + 10443 + 1997-02-12T00:00:00 + 517.44 + + + 10562 + 1997-06-09T00:00:00 + 488.70 + + + 10586 + 1997-07-02T00:00:00 + 23.80 + + + 10655 + 1997-09-03T00:00:00 + 154.40 + + + 10727 + 1997-11-03T00:00:00 + 1624.50 + + + 10812 + 1998-01-02T00:00:00 + 1692.80 + + + 10908 + 1998-02-26T00:00:00 + 663.10 + + + 10942 + 1998-03-11T00:00:00 + 560.00 + + + 11010 + 1998-04-09T00:00:00 + 645.00 + + + 11062 + 1998-04-30T00:00:00 + 406.40 + + +
+ + RICAR + Ricardo Adocicados +
Av.Copacabana, 267
+ Rio de Janeiro + RJ + 02389-890 + Brazil + (21) 555-3412 + + + 10287 + 1996-08-22T00:00:00 + 819.00 + + + 10299 + 1996-09-06T00:00:00 + 349.50 + + + 10447 + 1997-02-14T00:00:00 + 914.40 + + + 10481 + 1997-03-20T00:00:00 + 1472.00 + + + 10563 + 1997-06-10T00:00:00 + 965.00 + + + 10622 + 1997-08-06T00:00:00 + 560.00 + + + 10648 + 1997-08-28T00:00:00 + 372.38 + + + 10813 + 1998-01-05T00:00:00 + 602.40 + + + 10851 + 1998-01-26T00:00:00 + 2603.00 + + + 10877 + 1998-02-09T00:00:00 + 1955.12 + + + 11059 + 1998-04-29T00:00:00 + 1838.00 + + +
+ + RICSU + Richter Supermarkt +
Grenzacherweg 237
+ Genève + 1203 + Switzerland + 0897-034214 + + + 10255 + 1996-07-12T00:00:00 + 2490.50 + + + 10419 + 1997-01-20T00:00:00 + 2097.60 + + + 10537 + 1997-05-14T00:00:00 + 1823.80 + + + 10666 + 1997-09-12T00:00:00 + 4666.94 + + + 10751 + 1997-11-24T00:00:00 + 1631.48 + + + 10758 + 1997-11-28T00:00:00 + 1644.60 + + + 10931 + 1998-03-06T00:00:00 + 799.20 + + + 10951 + 1998-03-16T00:00:00 + 458.76 + + + 11033 + 1998-04-17T00:00:00 + 3232.80 + + + 11075 + 1998-05-06T00:00:00 + 498.10 + + +
+ + ROMEY + Romero y tomillo +
Gran Vía, 1
+ Madrid + 28001 + Spain + (91) 745 6200 + + + 10281 + 1996-08-14T00:00:00 + 86.50 + + + 10282 + 1996-08-15T00:00:00 + 155.40 + + + 10306 + 1996-09-16T00:00:00 + 498.50 + + + 10917 + 1998-03-02T00:00:00 + 365.89 + + + 11013 + 1998-04-09T00:00:00 + 361.00 + + +
+ + SANTG + Santé Gourmet +
Erling Skakkes gate 78
+ Stavern + 4110 + Norway + 07-98 92 35 + + + 10387 + 1996-12-18T00:00:00 + 1058.40 + + + 10520 + 1997-04-29T00:00:00 + 200.00 + + + 10639 + 1997-08-20T00:00:00 + 500.00 + + + 10831 + 1998-01-14T00:00:00 + 2684.40 + + + 10909 + 1998-02-26T00:00:00 + 670.00 + + + 11015 + 1998-04-10T00:00:00 + 622.35 + + +
+ + SAVEA + Save-a-lot Markets +
187 Suffolk Ln.
+ Boise + ID + 83720 + USA + (208) 555-8097 + + + 10324 + 1996-10-08T00:00:00 + 5275.72 + + + 10393 + 1996-12-25T00:00:00 + 2556.95 + + + 10398 + 1996-12-30T00:00:00 + 2505.60 + + + 10440 + 1997-02-10T00:00:00 + 4924.14 + + + 10452 + 1997-02-20T00:00:00 + 2018.50 + + + 10510 + 1997-04-18T00:00:00 + 4707.54 + + + 10555 + 1997-06-02T00:00:00 + 2944.40 + + + 10603 + 1997-07-18T00:00:00 + 1483.00 + + + 10607 + 1997-07-22T00:00:00 + 6475.40 + + + 10612 + 1997-07-28T00:00:00 + 6375.00 + + + 10627 + 1997-08-11T00:00:00 + 1185.75 + + + 10657 + 1997-09-04T00:00:00 + 4371.60 + + + 10678 + 1997-09-23T00:00:00 + 5256.50 + + + 10700 + 1997-10-10T00:00:00 + 1638.40 + + + 10711 + 1997-10-21T00:00:00 + 4451.70 + + + 10713 + 1997-10-22T00:00:00 + 2827.90 + + + 10714 + 1997-10-22T00:00:00 + 2205.75 + + + 10722 + 1997-10-29T00:00:00 + 1570.00 + + + 10748 + 1997-11-20T00:00:00 + 2196.00 + + + 10757 + 1997-11-27T00:00:00 + 3082.00 + + + 10815 + 1998-01-05T00:00:00 + 40.00 + + + 10847 + 1998-01-22T00:00:00 + 4931.92 + + + 10882 + 1998-02-11T00:00:00 + 892.64 + + + 10894 + 1998-02-18T00:00:00 + 2753.10 + + + 10941 + 1998-03-11T00:00:00 + 4011.75 + + + 10983 + 1998-03-27T00:00:00 + 720.90 + + + 10984 + 1998-03-30T00:00:00 + 1809.75 + + + 11002 + 1998-04-06T00:00:00 + 1811.10 + + + 11030 + 1998-04-17T00:00:00 + 12615.05 + + + 11031 + 1998-04-17T00:00:00 + 2393.50 + + + 11064 + 1998-05-01T00:00:00 + 4330.40 + + +
+ + SEVES + Seven Seas Imports +
90 Wadhurst Rd.
+ London + OX15 4NB + UK + (171) 555-1717 + + + 10359 + 1996-11-21T00:00:00 + 3471.68 + + + 10377 + 1996-12-09T00:00:00 + 863.60 + + + 10388 + 1996-12-19T00:00:00 + 1228.80 + + + 10472 + 1997-03-12T00:00:00 + 1036.80 + + + 10523 + 1997-05-01T00:00:00 + 2444.31 + + + 10547 + 1997-05-23T00:00:00 + 1792.80 + + + 10800 + 1997-12-26T00:00:00 + 1468.94 + + + 10804 + 1997-12-30T00:00:00 + 2278.40 + + + 10869 + 1998-02-04T00:00:00 + 1630.00 + + +
+ + SIMOB + Simons bistro +
Vinbæltet 34
+ København + 1734 + Denmark + 31 12 34 56 + + + 10341 + 1996-10-29T00:00:00 + 352.60 + + + 10417 + 1997-01-16T00:00:00 + 11188.40 + + + 10556 + 1997-06-03T00:00:00 + 835.20 + + + 10642 + 1997-08-22T00:00:00 + 696.00 + + + 10669 + 1997-09-15T00:00:00 + 570.00 + + + 10802 + 1997-12-29T00:00:00 + 2942.81 + + + 11074 + 1998-05-06T00:00:00 + 232.08 + + +
+ + SPECD + Spécialités du monde +
25, rue Lauriston
+ Paris + 75016 + France + (1) 47.55.60.10 + + + 10738 + 1997-11-12T00:00:00 + 52.35 + + + 10907 + 1998-02-25T00:00:00 + 108.50 + + + 10964 + 1998-03-20T00:00:00 + 2052.50 + + + 11043 + 1998-04-22T00:00:00 + 210.00 + + +
+ + SPLIR + Split Rail Beer & Ale +
P.O.Box 555
+ Lander + WY + 82520 + USA + (307) 555-4680 + + + 10271 + 1996-08-01T00:00:00 + 48.00 + + + 10329 + 1996-10-15T00:00:00 + 4578.43 + + + 10349 + 1996-11-08T00:00:00 + 141.60 + + + 10369 + 1996-12-02T00:00:00 + 2390.40 + + + 10385 + 1996-12-17T00:00:00 + 691.20 + + + 10432 + 1997-01-31T00:00:00 + 485.00 + + + 10756 + 1997-11-27T00:00:00 + 1990.00 + + + 10821 + 1998-01-08T00:00:00 + 678.00 + + + 10974 + 1998-03-25T00:00:00 + 439.00 + + +
+ + SUPRD + Suprêmes délices +
Boulevard Tirou, 255
+ Charleroi + B-6000 + Belgium + (071) 23 67 22 20 + + + 10252 + 1996-07-09T00:00:00 + 3597.90 + + + 10302 + 1996-09-10T00:00:00 + 2708.80 + + + 10458 + 1997-02-26T00:00:00 + 3891.00 + + + 10463 + 1997-03-04T00:00:00 + 713.30 + + + 10475 + 1997-03-14T00:00:00 + 1505.18 + + + 10767 + 1997-12-05T00:00:00 + 28.00 + + + 10841 + 1998-01-20T00:00:00 + 4581.00 + + + 10846 + 1998-01-22T00:00:00 + 1112.00 + + + 10885 + 1998-02-12T00:00:00 + 1209.00 + + + 10930 + 1998-03-06T00:00:00 + 2255.50 + + + 11035 + 1998-04-20T00:00:00 + 1754.50 + + + 11038 + 1998-04-21T00:00:00 + 732.60 + + +
+ + THEBI + The Big Cheese +
89 Jefferson Way, Suite 2
+ Portland + OR + 97201 + USA + (503) 555-3612 + + + 10310 + 1996-09-20T00:00:00 + 336.00 + + + 10708 + 1997-10-17T00:00:00 + 180.40 + + + 10805 + 1997-12-30T00:00:00 + 2775.00 + + + 10992 + 1998-04-01T00:00:00 + 69.60 + + +
+ + THECR + The Cracker Box +
55 Grizzly Peak Rd.
+ Butte + MT + 59801 + USA + (406) 555-5834 + + + 10624 + 1997-08-07T00:00:00 + 1393.24 + + + 10775 + 1997-12-12T00:00:00 + 228.00 + + + 11003 + 1998-04-06T00:00:00 + 326.00 + + +
+ + TOMSP + Toms Spezialitäten +
Luisenstr. 48
+ Münster + 44087 + Germany + 0251-031259 + + + 10438 + 1997-02-06T00:00:00 + 454.00 + + + 10446 + 1997-02-14T00:00:00 + 246.24 + + + 10548 + 1997-05-26T00:00:00 + 240.10 + + + 10608 + 1997-07-23T00:00:00 + 1064.00 + + + 10967 + 1998-03-23T00:00:00 + 910.40 + + +
+ + TORTU + Tortuga Restaurante +
Avda.Azteca 123
+ México D.F. + 05033 + Mexico + (5) 555-2933 + + + 10276 + 1996-08-08T00:00:00 + 420.00 + + + 10293 + 1996-08-29T00:00:00 + 848.70 + + + 10304 + 1996-09-12T00:00:00 + 954.40 + + + 10319 + 1996-10-02T00:00:00 + 1191.20 + + + 10518 + 1997-04-25T00:00:00 + 4150.05 + + + 10576 + 1997-06-23T00:00:00 + 838.45 + + + 10676 + 1997-09-22T00:00:00 + 534.85 + + + 10842 + 1998-01-20T00:00:00 + 975.00 + + + 10915 + 1998-02-27T00:00:00 + 539.50 + + + 11069 + 1998-05-04T00:00:00 + 360.00 + + +
+ + TRADH + Tradição Hipermercados +
Av.Inês de Castro, 414
+ São Paulo + SP + 05634-030 + Brazil + (11) 555-2167 + + + 10249 + 1996-07-05T00:00:00 + 1863.40 + + + 10292 + 1996-08-28T00:00:00 + 1296.00 + + + 10496 + 1997-04-04T00:00:00 + 190.00 + + + 10606 + 1997-07-22T00:00:00 + 1130.40 + + + 10830 + 1998-01-13T00:00:00 + 1974.00 + + + 10834 + 1998-01-15T00:00:00 + 1432.71 + + + 10839 + 1998-01-19T00:00:00 + 827.55 + + +
+ + TRAIH + Trail's Head Gourmet Provisioners +
722 DaVinci Blvd.
+ Kirkland + WA + 98034 + USA + (206) 555-8257 + + + 10574 + 1997-06-19T00:00:00 + 764.30 + + + 10577 + 1997-06-23T00:00:00 + 569.00 + + + 10822 + 1998-01-08T00:00:00 + 237.90 + + +
+ + VAFFE + Vaffeljernet +
Smagsløget 45
+ Århus + 8200 + Denmark + 86 21 32 43 + + + 10367 + 1996-11-28T00:00:00 + 834.20 + + + 10399 + 1996-12-31T00:00:00 + 1765.60 + + + 10465 + 1997-03-05T00:00:00 + 2518.00 + + + 10591 + 1997-07-07T00:00:00 + 812.50 + + + 10602 + 1997-07-17T00:00:00 + 48.75 + + + 10688 + 1997-10-01T00:00:00 + 3160.60 + + + 10744 + 1997-11-17T00:00:00 + 736.00 + + + 10769 + 1997-12-08T00:00:00 + 1684.28 + + + 10921 + 1998-03-03T00:00:00 + 1936.00 + + + 10946 + 1998-03-12T00:00:00 + 1407.50 + + + 10994 + 1998-04-02T00:00:00 + 940.50 + + +
+ + VICTE + Victuailles en stock +
2, rue du Commerce
+ Lyon + 69004 + France + 78.32.54.86 + + + 10251 + 1996-07-08T00:00:00 + 654.06 + + + 10334 + 1996-10-21T00:00:00 + 144.80 + + + 10450 + 1997-02-19T00:00:00 + 425.12 + + + 10459 + 1997-02-27T00:00:00 + 1659.20 + + + 10478 + 1997-03-18T00:00:00 + 471.20 + + + 10546 + 1997-05-23T00:00:00 + 2812.00 + + + 10806 + 1997-12-31T00:00:00 + 439.60 + + + 10814 + 1998-01-05T00:00:00 + 1788.45 + + + 10843 + 1998-01-21T00:00:00 + 159.00 + + + 10850 + 1998-01-23T00:00:00 + 629.00 + + +
+ + VINET + Vins et alcools Chevalier +
59 rue de l'Abbaye
+ Reims + 51100 + France + 26.47.15.10 + + + 10274 + 1996-08-06T00:00:00 + 538.60 + + + 10295 + 1996-09-02T00:00:00 + 121.60 + + + 10737 + 1997-11-11T00:00:00 + 139.80 + + + 10739 + 1997-11-12T00:00:00 + 240.00 + + +
+ + WANDK + Die Wandernde Kuh +
Adenauerallee 900
+ Stuttgart + 70563 + Germany + 0711-020361 + + + 10301 + 1996-09-09T00:00:00 + 755.00 + + + 10312 + 1996-09-23T00:00:00 + 1614.80 + + + 10348 + 1996-11-07T00:00:00 + 363.60 + + + 10356 + 1996-11-18T00:00:00 + 1106.40 + + + 10513 + 1997-04-22T00:00:00 + 1942.00 + + + 10632 + 1997-08-14T00:00:00 + 589.00 + + + 10640 + 1997-08-21T00:00:00 + 708.75 + + + 10651 + 1997-09-01T00:00:00 + 397.80 + + + 10668 + 1997-09-15T00:00:00 + 625.28 + + + 11046 + 1998-04-23T00:00:00 + 1485.80 + + +
+ + WARTH + Wartian Herkku +
Torikatu 38
+ Oulu + 90110 + Finland + 981-443655 + + + 10266 + 1996-07-26T00:00:00 + 346.56 + + + 10270 + 1996-08-01T00:00:00 + 1376.00 + + + 10320 + 1996-10-03T00:00:00 + 516.00 + + + 10333 + 1996-10-18T00:00:00 + 877.20 + + + 10412 + 1997-01-13T00:00:00 + 334.80 + + + 10416 + 1997-01-16T00:00:00 + 720.00 + + + 10437 + 1997-02-05T00:00:00 + 393.00 + + + 10455 + 1997-02-24T00:00:00 + 2684.00 + + + 10526 + 1997-05-05T00:00:00 + 1151.40 + + + 10553 + 1997-05-30T00:00:00 + 1546.30 + + + 10583 + 1997-06-30T00:00:00 + 2237.50 + + + 10636 + 1997-08-19T00:00:00 + 629.50 + + + 10750 + 1997-11-21T00:00:00 + 1590.56 + + + 10781 + 1997-12-17T00:00:00 + 975.88 + + + 11025 + 1998-04-15T00:00:00 + 270.00 + + +
+ + WELLI + Wellington Importadora +
Rua do Mercado, 12
+ Resende + SP + 08737-363 + Brazil + (14) 555-8122 + + + 10256 + 1996-07-15T00:00:00 + 517.80 + + + 10420 + 1997-01-21T00:00:00 + 1707.84 + + + 10585 + 1997-07-01T00:00:00 + 142.50 + + + 10644 + 1997-08-25T00:00:00 + 1371.80 + + + 10803 + 1997-12-30T00:00:00 + 1193.01 + + + 10809 + 1998-01-01T00:00:00 + 140.00 + + + 10900 + 1998-02-20T00:00:00 + 33.75 + + + 10905 + 1998-02-24T00:00:00 + 342.00 + + + 10935 + 1998-03-09T00:00:00 + 619.50 + + +
+ + WHITC + White Clover Markets +
305 - 14th Ave.S.Suite 3B
+ Seattle + WA + 98128 + USA + (206) 555-4112 + + + 10269 + 1996-07-31T00:00:00 + 642.20 + + + 10344 + 1996-11-01T00:00:00 + 2296.00 + + + 10469 + 1997-03-10T00:00:00 + 956.68 + + + 10483 + 1997-03-24T00:00:00 + 668.80 + + + 10504 + 1997-04-11T00:00:00 + 1388.50 + + + 10596 + 1997-07-11T00:00:00 + 1180.88 + + + 10693 + 1997-10-06T00:00:00 + 2071.20 + + + 10696 + 1997-10-08T00:00:00 + 996.00 + + + 10723 + 1997-10-30T00:00:00 + 468.45 + + + 10740 + 1997-11-13T00:00:00 + 1416.00 + + + 10861 + 1998-01-30T00:00:00 + 3523.40 + + + 10904 + 1998-02-24T00:00:00 + 1924.25 + + + 11032 + 1998-04-17T00:00:00 + 8902.50 + + + 11066 + 1998-05-01T00:00:00 + 928.75 + + +
+ + WILMK + Wilman Kala +
Keskuskatu 45
+ Helsinki + 21240 + Finland + 90-224 8858 + + + 10248 + 1996-07-04T00:00:00 + 440.00 + + + 10615 + 1997-07-30T00:00:00 + 120.00 + + + 10673 + 1997-09-18T00:00:00 + 412.35 + + + 10695 + 1997-10-07T00:00:00 + 642.00 + + + 10873 + 1998-02-06T00:00:00 + 336.80 + + + 10879 + 1998-02-10T00:00:00 + 611.30 + + + 10910 + 1998-02-26T00:00:00 + 452.90 + + + 11005 + 1998-04-07T00:00:00 + 586.00 + + +
+ + WOLZA + Wolski Zajazd +
ul.Filtrowa 68
+ Warszawa + 01-012 + Poland + (26) 642-7012 + + + 10374 + 1996-12-05T00:00:00 + 459.00 + + + 10611 + 1997-07-25T00:00:00 + 808.00 + + + 10792 + 1997-12-23T00:00:00 + 399.85 + + + 10870 + 1998-02-04T00:00:00 + 160.00 + + + 10906 + 1998-02-25T00:00:00 + 427.50 + + + 10998 + 1998-04-03T00:00:00 + 686.00 + + + 11044 + 1998-04-23T00:00:00 + 591.60 + + +
+
"; + } +} diff --git a/101-linq-samples/src/DataSources/Products.cs b/101-linq-samples/src/DataSources/Products.cs new file mode 100644 index 0000000..5069bcb --- /dev/null +++ b/101-linq-samples/src/DataSources/Products.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; + +namespace Try101LinqSamples +{ + public class Product + { + public int ProductID { get; set; } + public string ProductName { get; set; } + public string Category { get; set; } + public decimal UnitPrice { get; set; } + public int UnitsInStock { get; set; } + public override string ToString() => + $"ProductID={ProductID} ProductName={ProductName} Category={Category} UnitPrice={UnitPrice:C2} UnitsInStock={UnitsInStock}"; + + } + + public static class Products + { + public static List ProductList { get; } = + new List { + new Product { ProductID = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 39 }, + new Product { ProductID = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000M, UnitsInStock = 17 }, + new Product { ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000M, UnitsInStock = 13 }, + new Product { ProductID = 4, ProductName = "Chef Anton's Cajun Seasoning", Category = "Condiments", UnitPrice = 22.0000M, UnitsInStock = 53 }, + new Product { ProductID = 5, ProductName = "Chef Anton's Gumbo Mix", Category = "Condiments", UnitPrice = 21.3500M, UnitsInStock = 0 }, + new Product { ProductID = 6, ProductName = "Grandma's Boysenberry Spread", Category = "Condiments", UnitPrice = 25.0000M, UnitsInStock = 120 }, + new Product { ProductID = 7, ProductName = "Uncle Bob's Organic Dried Pears", Category = "Produce", UnitPrice = 30.0000M, UnitsInStock = 15 }, + new Product { ProductID = 8, ProductName = "Northwoods Cranberry Sauce", Category = "Condiments", UnitPrice = 40.0000M, UnitsInStock = 6 }, + new Product { ProductID = 9, ProductName = "Mishi Kobe Niku", Category = "Meat/Poultry", UnitPrice = 97.0000M, UnitsInStock = 29 }, + new Product { ProductID = 10, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 31 }, + new Product { ProductID = 11, ProductName = "Queso Cabrales", Category = "Dairy Products", UnitPrice = 21.0000M, UnitsInStock = 22 }, + new Product { ProductID = 12, ProductName = "Queso Manchego La Pastora", Category = "Dairy Products", UnitPrice = 38.0000M, UnitsInStock = 86 }, + new Product { ProductID = 13, ProductName = "Konbu", Category = "Seafood", UnitPrice = 6.0000M, UnitsInStock = 24 }, + new Product { ProductID = 14, ProductName = "Tofu", Category = "Produce", UnitPrice = 23.2500M, UnitsInStock = 35 }, + new Product { ProductID = 15, ProductName = "Genen Shouyu", Category = "Condiments", UnitPrice = 15.5000M, UnitsInStock = 39 }, + new Product { ProductID = 16, ProductName = "Pavlova", Category = "Confections", UnitPrice = 17.4500M, UnitsInStock = 29 }, + new Product { ProductID = 17, ProductName = "Alice Mutton", Category = "Meat/Poultry", UnitPrice = 39.0000M, UnitsInStock = 0 }, + new Product { ProductID = 18, ProductName = "Carnarvon Tigers", Category = "Seafood", UnitPrice = 62.5000M, UnitsInStock = 42 }, + new Product { ProductID = 19, ProductName = "Teatime Chocolate Biscuits", Category = "Confections", UnitPrice = 9.2000M, UnitsInStock = 25 }, + new Product { ProductID = 20, ProductName = "Sir Rodney's Marmalade", Category = "Confections", UnitPrice = 81.0000M, UnitsInStock = 40 }, + new Product { ProductID = 21, ProductName = "Sir Rodney's Scones", Category = "Confections", UnitPrice = 10.0000M, UnitsInStock = 3 }, + new Product { ProductID = 22, ProductName = "Gustaf's Knäckebröd", Category = "Grains/Cereals", UnitPrice = 21.0000M, UnitsInStock = 104 }, + new Product { ProductID = 23, ProductName = "Tunnbröd", Category = "Grains/Cereals", UnitPrice = 9.0000M, UnitsInStock = 61 }, + new Product { ProductID = 24, ProductName = "Guaraná Fantástica", Category = "Beverages", UnitPrice = 4.5000M, UnitsInStock = 20 }, + new Product { ProductID = 25, ProductName = "NuNuCa Nuß-Nougat-Creme", Category = "Confections", UnitPrice = 14.0000M, UnitsInStock = 76 }, + new Product { ProductID = 26, ProductName = "Gumbär Gummibärchen", Category = "Confections", UnitPrice = 31.2300M, UnitsInStock = 15 }, + new Product { ProductID = 27, ProductName = "Schoggi Schokolade", Category = "Confections", UnitPrice = 43.9000M, UnitsInStock = 49 }, + new Product { ProductID = 28, ProductName = "Rössle Sauerkraut", Category = "Produce", UnitPrice = 45.6000M, UnitsInStock = 26 }, + new Product { ProductID = 29, ProductName = "Thüringer Rostbratwurst", Category = "Meat/Poultry", UnitPrice = 123.7900M, UnitsInStock = 0 }, + new Product { ProductID = 30, ProductName = "Nord-Ost Matjeshering", Category = "Seafood", UnitPrice = 25.8900M, UnitsInStock = 10 }, + new Product { ProductID = 31, ProductName = "Gorgonzola Telino", Category = "Dairy Products", UnitPrice = 12.5000M, UnitsInStock = 0 }, + new Product { ProductID = 32, ProductName = "Mascarpone Fabioli", Category = "Dairy Products", UnitPrice = 32.0000M, UnitsInStock = 9 }, + new Product { ProductID = 33, ProductName = "Geitost", Category = "Dairy Products", UnitPrice = 2.5000M, UnitsInStock = 112 }, + new Product { ProductID = 34, ProductName = "Sasquatch Ale", Category = "Beverages", UnitPrice = 14.0000M, UnitsInStock = 111 }, + new Product { ProductID = 35, ProductName = "Steeleye Stout", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 20 }, + new Product { ProductID = 36, ProductName = "Inlagd Sill", Category = "Seafood", UnitPrice = 19.0000M, UnitsInStock = 112 }, + new Product { ProductID = 37, ProductName = "Gravad lax", Category = "Seafood", UnitPrice = 26.0000M, UnitsInStock = 11 }, + new Product { ProductID = 38, ProductName = "Côte de Blaye", Category = "Beverages", UnitPrice = 263.5000M, UnitsInStock = 17 }, + new Product { ProductID = 39, ProductName = "Chartreuse verte", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 69 }, + new Product { ProductID = 40, ProductName = "Boston Crab Meat", Category = "Seafood", UnitPrice = 18.4000M, UnitsInStock = 123 }, + new Product { ProductID = 41, ProductName = "Jack's New England Clam Chowder", Category = "Seafood", UnitPrice = 9.6500M, UnitsInStock = 85 }, + new Product { ProductID = 42, ProductName = "Singaporean Hokkien Fried Mee", Category = "Grains/Cereals", UnitPrice = 14.0000M, UnitsInStock = 26 }, + new Product { ProductID = 43, ProductName = "Ipoh Coffee", Category = "Beverages", UnitPrice = 46.0000M, UnitsInStock = 17 }, + new Product { ProductID = 44, ProductName = "Gula Malacca", Category = "Condiments", UnitPrice = 19.4500M, UnitsInStock = 27 }, + new Product { ProductID = 45, ProductName = "Rogede sild", Category = "Seafood", UnitPrice = 9.5000M, UnitsInStock = 5 }, + new Product { ProductID = 46, ProductName = "Spegesild", Category = "Seafood", UnitPrice = 12.0000M, UnitsInStock = 95 }, + new Product { ProductID = 47, ProductName = "Zaanse koeken", Category = "Confections", UnitPrice = 9.5000M, UnitsInStock = 36 }, + new Product { ProductID = 48, ProductName = "Chocolade", Category = "Confections", UnitPrice = 12.7500M, UnitsInStock = 15 }, + new Product { ProductID = 49, ProductName = "Maxilaku", Category = "Confections", UnitPrice = 20.0000M, UnitsInStock = 10 }, + new Product { ProductID = 50, ProductName = "Valkoinen suklaa", Category = "Confections", UnitPrice = 16.2500M, UnitsInStock = 65 }, + new Product { ProductID = 51, ProductName = "Manjimup Dried Apples", Category = "Produce", UnitPrice = 53.0000M, UnitsInStock = 20 }, + new Product { ProductID = 52, ProductName = "Filo Mix", Category = "Grains/Cereals", UnitPrice = 7.0000M, UnitsInStock = 38 }, + new Product { ProductID = 53, ProductName = "Perth Pasties", Category = "Meat/Poultry", UnitPrice = 32.8000M, UnitsInStock = 0 }, + new Product { ProductID = 54, ProductName = "Tourtière", Category = "Meat/Poultry", UnitPrice = 7.4500M, UnitsInStock = 21 }, + new Product { ProductID = 55, ProductName = "Pâté chinois", Category = "Meat/Poultry", UnitPrice = 24.0000M, UnitsInStock = 115 }, + new Product { ProductID = 56, ProductName = "Gnocchi di nonna Alice", Category = "Grains/Cereals", UnitPrice = 38.0000M, UnitsInStock = 21 }, + new Product { ProductID = 57, ProductName = "Ravioli Angelo", Category = "Grains/Cereals", UnitPrice = 19.5000M, UnitsInStock = 36 }, + new Product { ProductID = 58, ProductName = "Escargots de Bourgogne", Category = "Seafood", UnitPrice = 13.2500M, UnitsInStock = 62 }, + new Product { ProductID = 59, ProductName = "Raclette Courdavault", Category = "Dairy Products", UnitPrice = 55.0000M, UnitsInStock = 79 }, + new Product { ProductID = 60, ProductName = "Camembert Pierrot", Category = "Dairy Products", UnitPrice = 34.0000M, UnitsInStock = 19 }, + new Product { ProductID = 61, ProductName = "Sirop d'érable", Category = "Condiments", UnitPrice = 28.5000M, UnitsInStock = 113 }, + new Product { ProductID = 62, ProductName = "Tarte au sucre", Category = "Confections", UnitPrice = 49.3000M, UnitsInStock = 17 }, + new Product { ProductID = 63, ProductName = "Vegie-spread", Category = "Condiments", UnitPrice = 43.9000M, UnitsInStock = 24 }, + new Product { ProductID = 64, ProductName = "Wimmers gute Semmelknödel", Category = "Grains/Cereals", UnitPrice = 33.2500M, UnitsInStock = 22 }, + new Product { ProductID = 65, ProductName = "Louisiana Fiery Hot Pepper Sauce", Category = "Condiments", UnitPrice = 21.0500M, UnitsInStock = 76 }, + new Product { ProductID = 66, ProductName = "Louisiana Hot Spiced Okra", Category = "Condiments", UnitPrice = 17.0000M, UnitsInStock = 4 }, + new Product { ProductID = 67, ProductName = "Laughing Lumberjack Lager", Category = "Beverages", UnitPrice = 14.0000M, UnitsInStock = 52 }, + new Product { ProductID = 68, ProductName = "Scottish Longbreads", Category = "Confections", UnitPrice = 12.5000M, UnitsInStock = 6 }, + new Product { ProductID = 69, ProductName = "Gudbrandsdalsost", Category = "Dairy Products", UnitPrice = 36.0000M, UnitsInStock = 26 }, + new Product { ProductID = 70, ProductName = "Outback Lager", Category = "Beverages", UnitPrice = 15.0000M, UnitsInStock = 15 }, + new Product { ProductID = 71, ProductName = "Flotemysost", Category = "Dairy Products", UnitPrice = 21.5000M, UnitsInStock = 26 }, + new Product { ProductID = 72, ProductName = "Mozzarella di Giovanni", Category = "Dairy Products", UnitPrice = 34.8000M, UnitsInStock = 14 }, + new Product { ProductID = 73, ProductName = "Röd Kaviar", Category = "Seafood", UnitPrice = 15.0000M, UnitsInStock = 101 }, + new Product { ProductID = 74, ProductName = "Longlife Tofu", Category = "Produce", UnitPrice = 10.0000M, UnitsInStock = 4 }, + new Product { ProductID = 75, ProductName = "Rhönbräu Klosterbier", Category = "Beverages", UnitPrice = 7.7500M, UnitsInStock = 125 }, + new Product { ProductID = 76, ProductName = "Lakkalikööri", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 57 }, + new Product { ProductID = 77, ProductName = "Original Frankfurter grüne Soße", Category = "Condiments", UnitPrice = 13.0000M, UnitsInStock = 32 } + }; + } +} diff --git a/101-linq-samples/src/ElementOperations.cs b/101-linq-samples/src/ElementOperations.cs new file mode 100644 index 0000000..344588a --- /dev/null +++ b/101-linq-samples/src/ElementOperations.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class ElementOperations + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int FirstElement() + { + #region first-element + List products = GetProductList(); + + Product product12 = (from p in products + where p.ProductID == 12 + select p) + .First(); + + Console.WriteLine(product12); + #endregion + return 0; + } + + public int FirstMatchingElement() + { + #region first-matching-element + string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + string startsWithO = strings.First(s => s[0] == 'o'); + + Console.WriteLine($"A string starting with 'o': {startsWithO}"); + #endregion + return 0; + } + + public int MaybeFirstElement() + { + #region first-or-default + int[] numbers = { }; + + int firstNumOrDefault = numbers.FirstOrDefault(); + + Console.WriteLine(firstNumOrDefault); + #endregion + return 0; + } + + public int MaybeFirstMatchingElement() + { + #region first-matching-or-default + List products = GetProductList(); + + Product product789 = products.FirstOrDefault(p => p.ProductID == 789); + + Console.WriteLine($"Product 789 exists: {product789 != null}"); + #endregion + return 0; + } + + public int ElementAtPosition() + { + #region element-at + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + int fourthLowNum = ( + from n in numbers + where n > 5 + select n) + .ElementAt(1); // second number is index 1 because sequences use 0-based indexing + + Console.WriteLine($"Second number > 5: {fourthLowNum}"); + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/Generators.cs b/101-linq-samples/src/Generators.cs new file mode 100644 index 0000000..1c7c5cb --- /dev/null +++ b/101-linq-samples/src/Generators.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq; + +namespace Try101LinqSamples +{ + public class Generators + { + public int RangeOfIntegers() + { + #region generate-range + var numbers = from n in Enumerable.Range(100, 50) + select (Number: n, OddEven: n % 2 == 1 ? "odd" : "even"); + + foreach (var n in numbers) + { + Console.WriteLine("The number {0} is {1}.", n.Number, n.OddEven); + } + #endregion + return 0; + } + + public int RepeatNumber() + { + #region generate-repeat + var numbers = Enumerable.Repeat(7, 10); + + foreach (var n in numbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/Groupings.cs b/101-linq-samples/src/Groupings.cs new file mode 100644 index 0000000..e8e767c --- /dev/null +++ b/101-linq-samples/src/Groupings.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class Groupings + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + + public int GroupingSyntax() + { + #region groupby-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var numberGroups = from n in numbers + group n by n % 5 into g + select (Remainder: g.Key, Numbers: g); + + foreach (var g in numberGroups) + { + Console.WriteLine($"Numbers with a remainder of {g.Remainder} when divided by 5:"); + foreach (var n in g.Numbers) + { + Console.WriteLine(n); + } + } + #endregion + return 0; + } + + public int GroupByProperty() + { + #region groupby-property + string[] words = { "blueberry", "chimpanzee", "abacus", "banana", "apple", "cheese" }; + + var wordGroups = from w in words + group w by w[0] into g + select (FirstLetter: g.Key, Words: g); + + foreach (var g in wordGroups) + { + Console.WriteLine("Words that start with the letter '{0}':", g.FirstLetter); + foreach (var w in g.Words) + { + Console.WriteLine(w); + } + } + #endregion + return 0; + } + + public int GroupByCategory() + { + #region groupby-category + List products = GetProductList(); + + var orderGroups = from p in products + group p by p.Category into g + select (Category: g.Key, Products: g); + + foreach(var orderGroup in orderGroups) + { + Console.WriteLine($"Products in {orderGroup.Category} category:"); + foreach(var product in orderGroup.Products) + { + Console.WriteLine($"\t{product}"); + } + } + #endregion + return 0; + } + + public int NestedGrouBy() + { + #region nested-groupby + List customers = GetCustomerList(); + + var customerOrderGroups = from c in customers + select + ( + c.CompanyName, + YearGroups: from o in c.Orders + group o by o.OrderDate.Year into yg + select + ( + Year: yg.Key, + MonthGroups: from o in yg + group o by o.OrderDate.Month into mg + select (Month: mg.Key, Orders: mg) + ) + ); + + foreach( var ordersByCustomer in customerOrderGroups) + { + Console.WriteLine($"Customer Name: {ordersByCustomer.CompanyName}"); + foreach(var ordersByYear in ordersByCustomer.YearGroups) + { + Console.WriteLine($"\tYear: {ordersByYear.Year}"); + foreach(var ordersByMonth in ordersByYear.MonthGroups) + { + Console.WriteLine($"\t\tMonth: {ordersByMonth.Month}"); + foreach(var order in ordersByMonth.Orders) + { + Console.WriteLine($"\t\t\tOrder: {order}"); + } + } + } + } + #endregion + return 0; + } + + public int GroupByCustomComparer() + { + #region groupby-custom-comparer + string[] anagrams = { "from ", " salt", " earn ", " last ", " near ", " form " }; + + var orderGroups = anagrams.GroupBy(w => w.Trim(), new AnagramEqualityComparer()); + + foreach(var set in orderGroups) + { + // The key would be the first item in the set + foreach(var word in set) + { + Console.WriteLine(word); + } + Console.WriteLine("..."); + } + #endregion + return 0; + } + + public int NestedGroupByCustom() + { + #region nested-groupby-custom + string[] anagrams = { "from ", " salt", " earn ", " last ", " near ", " form " }; + + var orderGroups = anagrams.GroupBy( + w => w.Trim(), + a => a.ToUpper(), + new AnagramEqualityComparer() + ); + foreach (var set in orderGroups) + { + Console.WriteLine(set.Key); + foreach (var word in set) + { + Console.WriteLine($"\t{word}"); + } + } + + #endregion + return 0; + } + } + + #region anagram-comparer + public class AnagramEqualityComparer : IEqualityComparer + { + public bool Equals(string x, string y) => getCanonicalString(x) == getCanonicalString(y); + + public int GetHashCode(string obj) => getCanonicalString(obj).GetHashCode(); + + private string getCanonicalString(string word) + { + char[] wordChars = word.ToCharArray(); + Array.Sort(wordChars); + return new string(wordChars); + } + } + #endregion +} diff --git a/101-linq-samples/src/JoinOperations.cs b/101-linq-samples/src/JoinOperations.cs new file mode 100644 index 0000000..c4ce5dd --- /dev/null +++ b/101-linq-samples/src/JoinOperations.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class JoinOperations + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int CrossJoinQuery() + { + #region cross-join + string[] categories = { + "Beverages", + "Condiments", + "Vegetables", + "Dairy Products", + "Seafood" + }; + + List products = GetProductList(); + + var q = from c in categories + join p in products on c equals p.Category + select (Category: c, p.ProductName); + + foreach (var v in q) + { + Console.WriteLine(v.ProductName + ": " + v.Category); + } + #endregion + return 0; + } + + public int GroupJoinQquery() + { + #region group-join + string[] categories = { + "Beverages", + "Condiments", + "Vegetables", + "Dairy Products", + "Seafood" + }; + + List products = GetProductList(); + + var q = from c in categories + join p in products on c equals p.Category into ps + select (Category: c, Products: ps); + + foreach (var v in q) + { + Console.WriteLine(v.Category + ":"); + foreach (var p in v.Products) + { + Console.WriteLine(" " + p.ProductName); + } + } + #endregion + return 0; + } + + public int CrossGroupJoin() + { + #region cross-group-join + string[] categories = { + "Beverages", + "Condiments", + "Vegetables", + "Dairy Products", + "Seafood" + }; + + List products = GetProductList(); + + var q = from c in categories + join p in products on c equals p.Category into ps + from p in ps + select (Category: c, p.ProductName); + + foreach (var v in q) + { + Console.WriteLine(v.ProductName + ": " + v.Category); + } + #endregion + return 0; + } + + public int LeftOuterJoin() + { + #region left-outer-join + string[] categories = { + "Beverages", + "Condiments", + "Vegetables", + "Dairy Products", + "Seafood" + }; + + List products = GetProductList(); + + var q = from c in categories + join p in products on c equals p.Category into ps + from p in ps.DefaultIfEmpty() + select (Category: c, ProductName: p == null ? "(No products)" : p.ProductName); + + foreach (var v in q) + { + Console.WriteLine($"{v.ProductName}: {v.Category}"); + } + #endregion + return 0; + } + } +} + + diff --git a/101-linq-samples/src/Orderings.cs b/101-linq-samples/src/Orderings.cs new file mode 100644 index 0000000..d3fc7ab --- /dev/null +++ b/101-linq-samples/src/Orderings.cs @@ -0,0 +1,229 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +namespace Try101LinqSamples +{ + public class Orderings + { + public List GetProductList() => Products.ProductList; + + public List GetCustomerList() => Customers.CustomerList; + + public int OrderbySyntax() + { + #region orderby-syntax + string[] words = { "cherry", "apple", "blueberry" }; + + var sortedWords = from word in words + orderby word + select word; + + Console.WriteLine("The sorted list of words:"); + foreach (var w in sortedWords) + { + Console.WriteLine(w); + } + #endregion + return 0; + } + + public int OrderbyProperty() + { + #region orderby-property + string[] words = { "cherry", "apple", "blueberry" }; + + var sortedWords = from word in words + orderby word.Length + select word; + + Console.WriteLine("The sorted list of words (by length):"); + foreach (var w in sortedWords) + { + Console.WriteLine(w); + } + #endregion + return 0; + } + + public int OrderByProducts() + { + #region orderby-user-types + List products = GetProductList(); + + var sortedProducts = from prod in products + orderby prod.ProductName + select prod; + + foreach (var product in sortedProducts) + { + Console.WriteLine(product); + } + #endregion + return 0; + } + + #region custom-comparer + // Custom comparer for use with ordering operators + public class CaseInsensitiveComparer : IComparer + { + public int Compare(string x, string y) => + string.Compare(x, y, StringComparison.OrdinalIgnoreCase); + } + #endregion + + public int OrderByWithCustomComparer() + { + #region orderby-custom-comparer + string[] words = { "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" }; + + var sortedWords = words.OrderBy(a => a, new CaseInsensitiveComparer()); + + foreach(var word in sortedWords) + { + Console.WriteLine(word); + } + #endregion + return 0; + } + + public int OrderByDescendingSyntax() + { + #region orderbydescending-syntax + double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 }; + + var sortedDoubles = from d in doubles + orderby d descending + select d; + + Console.WriteLine("The doubles from highest to lowest:"); + foreach (var d in sortedDoubles) + { + Console.WriteLine(d); + } + #endregion + return 0; + } + + public int OrderProductsDescending() + { + #region orderby-descending-type + List products = GetProductList(); + + var sortedProducts = from prod in products + orderby prod.UnitsInStock descending + select prod; + + foreach(var product in sortedProducts) + { + Console.WriteLine(product); + } + #endregion + return 0; + } + + public int DescendingCustomComparer() + { + #region desc-custom-comparer + string[] words = { "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" }; + + var sortedWords = words.OrderByDescending(a => a, new CaseInsensitiveComparer()); + + foreach(var word in sortedWords) + { + Console.WriteLine(word); + } + #endregion + return 0; + } + + public int ThenBySyntax() + { + #region thenby-syntax + string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var sortedDigits = from digit in digits + orderby digit.Length, digit + select digit; + + Console.WriteLine("Sorted digits:"); + foreach (var d in sortedDigits) + { + Console.WriteLine(d); + } + #endregion + return 0; + } + + public int ThenByCustom() + { + #region thenby-custom + string[] words = { "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" }; + + var sortedWords = words + .OrderBy(a => a.Length) + .ThenBy(a => a, new CaseInsensitiveComparer()); + + foreach(var word in sortedWords) + { + Console.WriteLine(word); + } + #endregion + return 0; + } + + public int ThenByDifferentOrdering() + { + #region thenby-ordering + List products = GetProductList(); + + var sortedProducts = from prod in products + orderby prod.Category, prod.UnitPrice descending + select prod; + + foreach(var product in sortedProducts) + { + Console.WriteLine(product); + } + #endregion + return 0; + } + + public int CustomThenByDescending() + { + #region thenby-custom-descending + string[] words = { "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" }; + + var sortedWords = words + .OrderBy(a => a.Length) + .ThenByDescending(a => a, new CaseInsensitiveComparer()); + + foreach (var word in sortedWords) + { + Console.WriteLine(word); + } + #endregion + return 0; + } + + public int OrderingReversal() + { + #region reverse + string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var reversedIDigits = ( + from digit in digits + where digit[1] == 'i' + select digit) + .Reverse(); + + Console.WriteLine("A backwards list of the digits with a second character of 'i':"); + foreach (var d in reversedIDigits) + { + Console.WriteLine(d); + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/Partitions.cs b/101-linq-samples/src/Partitions.cs new file mode 100644 index 0000000..5ed3fc7 --- /dev/null +++ b/101-linq-samples/src/Partitions.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class Partitions + { + public List GetProductList() => Products.ProductList; + + public List GetCustomerList() => Customers.CustomerList; + + public int TakeSyntax() + { + #region take-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var first3Numbers = numbers.Take(3); + + Console.WriteLine("First 3 numbers:"); + foreach (var n in first3Numbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int NestedTake() + { + #region nested-take + List customers = GetCustomerList(); + + var first3WAOrders = ( + from cust in customers + from order in cust.Orders + where cust.Region == "WA" + select (cust.CustomerID, order.OrderID, order.OrderDate)) + .Take(3); + + Console.WriteLine("First 3 orders in WA:"); + foreach (var order in first3WAOrders) + { + Console.WriteLine(order); + } + #endregion + return 0; + + } + + public int SkipSyntax() + + { + #region skip-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var allButFirst4Numbers = numbers.Skip(4); + + Console.WriteLine("All but first 4 numbers:"); + foreach (var n in allButFirst4Numbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int NestedSkip() + { + #region nested-skip + List customers = GetCustomerList(); + + var waOrders = from cust in customers + from order in cust.Orders + where cust.Region == "WA" + select (cust.CustomerID, order.OrderID, order.OrderDate); + + var allButFirst2Orders = waOrders.Skip(2); + + Console.WriteLine("All but first 2 orders in WA:"); + foreach (var order in allButFirst2Orders) + { + Console.WriteLine(order); + } + #endregion + return 1; + } + + public int TakeWhileSyntax() + { + #region takewhile-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6); + + Console.WriteLine("First numbers less than 6:"); + foreach (var num in firstNumbersLessThan6) + { + Console.WriteLine(num); + } + #endregion + return 0; + } + + public int IndexedTakeWhile() + { + #region indexed-takewhile + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index); + + Console.WriteLine("First numbers not less than their position:"); + foreach (var n in firstSmallNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int SkipWhileSyntax() + { + #region skipwhile-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + // In the lambda expression, 'n' is the input parameter that identifies each + // element in the collection in succession. It is is inferred to be + // of type int because numbers is an int array. + var allButFirst3Numbers = numbers.SkipWhile(n => n % 3 != 0); + + Console.WriteLine("All elements starting from first element divisible by 3:"); + foreach (var n in allButFirst3Numbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int IndexedSkipWhile() + { + #region indexed-skipwhile + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var laterNumbers = numbers.SkipWhile((n, index) => n >= index); + + Console.WriteLine("All elements starting from first element less than its position:"); + foreach (var n in laterNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + } +} diff --git a/101-linq-samples/src/Program.cs b/101-linq-samples/src/Program.cs new file mode 100644 index 0000000..b16d678 --- /dev/null +++ b/101-linq-samples/src/Program.cs @@ -0,0 +1,293 @@ +using System; + +namespace Try101LinqSamples +{ + class Program + { + ///Takes in the --region option from the code fence options in markdown + ///Takes in the --session option from the code fence options in markdown + ///Takes in the --package option from the code fence options in markdown + ///Takes in the --project option from the code fence options in markdown + ///Takes in any additional arguments passed in the code fence options in markdown + ///To learn more see our documentation + static int Main( + string region = null, + string session = null, + string package = null, + string project = null, + string[] args = null) + { + return region switch + { + "where-syntax" => new Restrictions().LowNumbers(), + "where-property" => new Restrictions().ProductsOutOfStock(), + "where-multiple-properties" => new Restrictions().ExpensiveProductsInStock(), + "where-drilldown" => new Restrictions().DisplayCustomerOrders(), + "where-indexed" => new Restrictions().IndexedWhere(), + + "select-syntax" => new Projections().SelectSyntax(), + "select-property" => new Projections().SelectProperty(), + "select-transform" => new Projections().TransformWithSelect(), + "select-case-anonymous" => new Projections().SelectByCaseAnonymous(), + "select-case-tuple" => new Projections().SelectByCaseTuple(), + "select-new-type" => new Projections().SelectAnonymousConstructions(), + "select-new-type-tuple" => new Projections().SelectTupleConstructions(), + "select-subset-properties" => new Projections().SelectPropertySubset(), + "select-with-index" => new Projections().SelectWithIndex(), + "select-with-where" => new Projections().SelectWithWhere(), + "select-many-syntax" => new Projections().SelectFromMultipleSequences(), + "select-many-drilldown" => new Projections().SelectFromChildSequence(), + "select-many-filter" => new Projections().SelectManyWithWhere(), + "select-many-assignment" => new Projections().SelectManyWhereAssignment(), + "multiple-where-clauses" => new Projections().SelectMultipleWhereClauses(), + "indexed-select-many" => new Projections().IndexedSelectMany(), + + "take-syntax" => new Partitions().TakeSyntax(), + "nested-take" => new Partitions().NestedTake(), + "skip-syntax" => new Partitions().SkipSyntax(), + "nested-skip" => new Partitions().NestedSkip(), + "takewhile-syntax" => new Partitions().TakeWhileSyntax(), + "indexed-takewhile" => new Partitions().IndexedTakeWhile(), + "skipwhile-syntax" => new Partitions().SkipWhileSyntax(), + "indexed-skipwhile" => new Partitions().IndexedSkipWhile(), + + "orderby-syntax" => new Orderings().OrderbySyntax(), + "orderby-property" => new Orderings().OrderbyProperty(), + "orderby-user-types" => new Orderings().OrderByProducts(), + "custom-comparer" => session switch + { + "orderby-custom" => new Orderings().OrderByWithCustomComparer(), + "orderby-custom-descending" => new Orderings().DescendingCustomComparer(), + "orderby-custom-thenby" => new Orderings().ThenByCustom(), + "orderby-custom-descending-thenby" => new Orderings().CustomThenByDescending(), + _ => MissingTag(session, false), + }, + "orderby-custom-comparer" => new Orderings().OrderByWithCustomComparer(), + "orderbydescending-syntax" => new Orderings().OrderByDescendingSyntax(), + "orderby-descending-type" => new Orderings().OrderProductsDescending(), + "desc-custom-comparer" => new Orderings().DescendingCustomComparer(), + "thenby-syntax" => new Orderings().ThenBySyntax(), + "thenby-custom" => new Orderings().ThenByCustom(), + "thenby-ordering" => new Orderings().ThenByDifferentOrdering(), + "thenby-custom-descending" => new Orderings().CustomThenByDescending(), + "reverse" => new Orderings().OrderingReversal(), + + "groupby-syntax" => new Groupings().GroupingSyntax(), + "groupby-property" => new Groupings().GroupByProperty(), + "groupby-category" => new Groupings().GroupByCategory(), + "nested-groupby" => new Groupings().NestedGrouBy(), + "anagram-comparer" => session switch + { + "groupby-custom-comparer" => new Groupings().GroupByCustomComparer(), + "nested-groupby-custom" => new Groupings().NestedGroupByCustom(), + _ => MissingTag(session, false), + + }, + "groupby-custom-comparer" => new Groupings().GroupByCustomComparer(), + "nested-groupby-custom" => new Groupings().NestedGroupByCustom(), + + "distinct-syntax" => new SetOperations().DistinctSyntax(), + "distinct-property-values" => new SetOperations().DistinctPropertyValues(), + "union-syntax" => new SetOperations().UnionSyntax(), + "union-query-results" => new SetOperations().UnionOfQueryResults(), + "intersect-syntax" => new SetOperations().IntersectSynxtax(), + "intersect-different-queries" => new SetOperations().IntersectQueryResults(), + "difference-of-sets" => new SetOperations().DifferenceOfSets(), + "difference-of-queries" => new SetOperations().DifferenceOfQueries(), + + "convert-to-array" => new Conversions().ConvertToArray(), + "convert-to-list" => new Conversions().ConvertToList(), + "convert-to-dictionary" => new Conversions().ConvertToDictionary(), + "convert-to-type" => new Conversions().ConvertSelectedItems(), + + "first-element" => new ElementOperations().FirstElement(), + "first-matching-element" => new ElementOperations().FirstMatchingElement(), + "first-or-default" => new ElementOperations().MaybeFirstElement(), + "first-matching-or-default" => new ElementOperations().MaybeFirstMatchingElement(), + "element-at" => new ElementOperations().ElementAtPosition(), + + "generate-range" => new Generators().RangeOfIntegers(), + "generate-repeat" => new Generators().RepeatNumber(), + + "any-matches" => new Quantifiers().AnyMatchingElements(), + "any-grouped" => new Quantifiers().GroupedAnyMatchedElements(), + "all-match" => new Quantifiers().AllMatchedElements(), + "all-grouped" => new Quantifiers().GroupedAllMatchedElements(), + + "count-syntax" => new AggregateOperators().CountSyntax(), + "count-conditional" => new AggregateOperators().CountConditional(), + "nested-count" => new AggregateOperators().NestedCount(), + "grouped-count" => new AggregateOperators().GroupedCount(), + "sum-syntax" => new AggregateOperators().SumSyntax(), + "sum-of-projection" => new AggregateOperators().SumProjection(), + "grouped-sum" => new AggregateOperators().SumGrouped(), + "min-syntax" => new AggregateOperators().MinSyntax(), + "min-projection" => new AggregateOperators().MinProjection(), + "min-grouped" => new AggregateOperators().MinGrouped(), + "min-each-group" => new AggregateOperators().MinEachGroup(), + "max-syntax" => new AggregateOperators().MaxSyntax(), + "max-projection" => new AggregateOperators().MaxProjection(), + "max-grouped" => new AggregateOperators().MaxGrouped(), + "max-each-group" => new AggregateOperators().MaxEachGroup(), + "average-syntax" => new AggregateOperators().AverageSyntax(), + "average-projection" => new AggregateOperators().AverageProjection(), + "average-grouped" => new AggregateOperators().AverageGrouped(), + "aggregate-syntax" => new AggregateOperators().AggregateSyntax(), + "aggregate-seeded" => new AggregateOperators().SeededAggregate(), + + "concat-series" => new SequenceOperations().ConcatSeries(), + "concat-projections" => new SequenceOperations().ConcatProjection(), + "equal-sequence" => new SequenceOperations().EqualSequence(), + "dot-product" => new SequenceOperations().DotProduct(), + + "deferred-execution" => new QueryExecution().DeferredExecution(), + "eager-execution" => new QueryExecution().EagerExecution(), + "reuse-query" => new QueryExecution().ReuseQueryDefinition(), + + "cross-join" => new JoinOperations().CrossJoinQuery(), + "group-join" => new JoinOperations().GroupJoinQquery(), + "cross-group-join" => new JoinOperations().CrossGroupJoin(), + "left-outer-join" => new JoinOperations().LeftOuterJoin(), + + null => RunAll(), + _ => MissingTag(region), + }; + } + + private static int MissingTag(string tag, bool region = true) + { + Console.WriteLine($"No code snippet configured for {(region ? "region" : "session")}: {tag}"); + return 1; + } + private static int RunAll() + { + // 1- 5 + new Restrictions().LowNumbers(); + new Restrictions().ProductsOutOfStock(); + new Restrictions().ExpensiveProductsInStock(); + new Restrictions().DisplayCustomerOrders(); + new Restrictions().IndexedWhere(); + + // 6 - 19 (+ 2 for tuples) + new Projections().SelectSyntax(); + new Projections().SelectProperty(); + new Projections().TransformWithSelect(); + new Projections().SelectByCaseAnonymous(); + new Projections().SelectByCaseTuple(); + new Projections().SelectAnonymousConstructions(); + new Projections().SelectTupleConstructions(); + new Projections().SelectPropertySubset(); + new Projections().SelectWithIndex(); + new Projections().SelectWithWhere(); + new Projections().SelectFromMultipleSequences(); + new Projections().SelectFromChildSequence(); + new Projections().SelectManyWithWhere(); + new Projections().SelectManyWhereAssignment(); + new Projections().SelectMultipleWhereClauses(); + new Projections().IndexedSelectMany(); + + // 20 - 27 + new Partitions().TakeSyntax(); + new Partitions().NestedTake(); + new Partitions().SkipSyntax(); + new Partitions().NestedSkip(); + new Partitions().TakeWhileSyntax(); + new Partitions().IndexedTakeWhile(); + new Partitions().SkipWhileSyntax(); + new Partitions().IndexedSkipWhile(); + + // Ordering: 28-39 + new Orderings().OrderbySyntax(); + new Orderings().OrderbyProperty(); + new Orderings().OrderByProducts(); + new Orderings().OrderByWithCustomComparer(); + new Orderings().OrderByDescendingSyntax(); + new Orderings().OrderProductsDescending(); + new Orderings().DescendingCustomComparer(); + new Orderings().ThenBySyntax(); + new Orderings().ThenByCustom(); + new Orderings().ThenByDifferentOrdering(); + new Orderings().CustomThenByDescending(); + new Orderings().OrderingReversal(); + + // Grouping: 40 - 45 + new Groupings().GroupingSyntax(); + new Groupings().GroupByProperty(); + new Groupings().GroupByCategory(); + new Groupings().NestedGrouBy(); + new Groupings().GroupByCustomComparer(); + new Groupings().NestedGroupByCustom(); + + // Set operations: 46 - 53 + new SetOperations().DistinctSyntax(); + new SetOperations().DistinctPropertyValues(); + new SetOperations().UnionSyntax(); + new SetOperations().UnionOfQueryResults(); + new SetOperations().IntersectSynxtax(); + new SetOperations().IntersectQueryResults(); + new SetOperations().DifferenceOfSets(); + new SetOperations().DifferenceOfQueries(); + + // Conversion Operators: 54 - 57 + new Conversions().ConvertToArray(); + new Conversions().ConvertToList(); + new Conversions().ConvertToDictionary(); + new Conversions().ConvertSelectedItems(); + + // Element operators: 58-64 (60 is missing.) + new ElementOperations().FirstElement(); + new ElementOperations().FirstMatchingElement(); + new ElementOperations().MaybeFirstElement(); + new ElementOperations().MaybeFirstMatchingElement(); + new ElementOperations().ElementAtPosition(); + + // Generator operators: 65,66 + new Generators().RangeOfIntegers(); + new Generators().RepeatNumber(); + + // Quantifiers: 67 - 72 (68 and 71 are missing) + new Quantifiers().AnyMatchingElements(); + new Quantifiers().GroupedAnyMatchedElements(); + new Quantifiers().AllMatchedElements(); + new Quantifiers().GroupedAllMatchedElements(); + + // Aggregators: 73 - 93 (75 is missing) + new AggregateOperators().CountSyntax(); + new AggregateOperators().CountConditional(); + new AggregateOperators().NestedCount(); + new AggregateOperators().GroupedCount(); + new AggregateOperators().SumSyntax(); + new AggregateOperators().SumProjection(); + new AggregateOperators().SumGrouped(); + new AggregateOperators().MinSyntax(); + new AggregateOperators().MinProjection(); + new AggregateOperators().MinGrouped(); + new AggregateOperators().MinEachGroup(); + new AggregateOperators().MaxSyntax(); + new AggregateOperators().MaxProjection(); + new AggregateOperators().MaxGrouped(); + new AggregateOperators().MaxEachGroup(); + new AggregateOperators().AverageSyntax(); + new AggregateOperators().AverageProjection(); + new AggregateOperators().AverageGrouped(); + new AggregateOperators().AggregateSyntax(); + + // Miscellaneous: + new SequenceOperations().ConcatSeries(); + new SequenceOperations().ConcatProjection(); + new SequenceOperations().EqualSequence(); + new SequenceOperations().Linq97(); + + new QueryExecution().DeferredExecution(); + new QueryExecution().EagerExecution(); + new QueryExecution().ReuseQueryDefinition(); + + new JoinOperations().CrossJoinQuery(); + new JoinOperations().GroupJoinQquery(); + new JoinOperations().CrossGroupJoin(); + new JoinOperations().LeftOuterJoin(); + + return 0; + } + } +} diff --git a/101-linq-samples/src/Projections.cs b/101-linq-samples/src/Projections.cs new file mode 100644 index 0000000..c38c138 --- /dev/null +++ b/101-linq-samples/src/Projections.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Try101LinqSamples +{ + public class Projections + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int SelectSyntax() + { + #region select-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var numsPlusOne = from n in numbers + select n + 1; + + Console.WriteLine("Numbers + 1:"); + foreach (var i in numsPlusOne) + { + Console.WriteLine(i); + } + return 0; + #endregion + } + + public int SelectProperty() + { + #region select-property + List products = GetProductList(); + + var productNames = from p in products + select p.ProductName; + + Console.WriteLine("Product Names:"); + foreach (var productName in productNames) + { + Console.WriteLine(productName); + } + #endregion + return 0; + } + + public int TransformWithSelect() + { + #region select-transform + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var textNums = from n in numbers + select strings[n]; + + Console.WriteLine("Number strings:"); + foreach (var s in textNums) + { + Console.WriteLine(s); + } + #endregion + return 0; + } + + public int SelectByCaseAnonymous() + { + #region select-case-anonymous + string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" }; + + var upperLowerWords = from w in words + select new { Upper = w.ToUpper(), Lower = w.ToLower() }; + + foreach (var ul in upperLowerWords) + { + Console.WriteLine($"Uppercase: {ul.Upper}, Lowercase: {ul.Lower}"); + } + #endregion + return 0; + } + + public int SelectByCaseTuple() + { + #region select-case-tuple + string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" }; + + var upperLowerWords = from w in words + select (Upper : w.ToUpper(), Lower : w.ToLower()); + + foreach (var ul in upperLowerWords) + { + Console.WriteLine($"Uppercase: {ul.Upper}, Lowercase: {ul.Lower}"); + } + #endregion + return 0; + } + + public int SelectAnonymousConstructions() + { + #region select-new-type + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var digitOddEvens = from n in numbers + select new { Digit = strings[n], Even = (n % 2 == 0) }; + + foreach (var d in digitOddEvens) + { + Console.WriteLine($"The digit {d.Digit} is {(d.Even ? "even" : "odd")}."); + } + #endregion + return 0; + } + + public int SelectTupleConstructions() + { + #region select-new-type-tuple + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var digitOddEvens = from n in numbers + select (Digit : strings[n], Even : (n % 2 == 0)); + + foreach (var d in digitOddEvens) + { + Console.WriteLine($"The digit {d.Digit} is {(d.Even ? "even" : "odd")}."); + } + #endregion + return 0; + } + + public int SelectPropertySubset() + { + #region select-subset-properties + List products = GetProductList(); + + var productInfos = from p in products + select (p.ProductName, p.Category, Price : p.UnitPrice); + + Console.WriteLine("Product Info:"); + foreach (var productInfo in productInfos) + { + Console.WriteLine($"{productInfo.ProductName} is in the category {productInfo.Category} and costs {productInfo.Price} per unit."); + } + #endregion + return 0; + } + + public int SelectWithIndex() + { + #region select-with-index + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var numsInPlace = numbers.Select((num, index) => (Num : num, InPlace : (num == index))); + + Console.WriteLine("Number: In-place?"); + foreach (var n in numsInPlace) + { + Console.WriteLine($"{n.Num}: {n.InPlace}"); + } + #endregion + return 0; + } + + public int SelectWithWhere() + { + #region select-with-where + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var lowNums = from n in numbers + where n < 5 + select digits[n]; + + Console.WriteLine("Numbers < 5:"); + foreach (var num in lowNums) + { + Console.WriteLine(num); + } + #endregion + return 0; + } + + public int SelectFromMultipleSequences() + { + #region select-many-syntax + int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; + int[] numbersB = { 1, 3, 5, 7, 8 }; + + var pairs = from a in numbersA + from b in numbersB + where a < b + select (a, b); + + Console.WriteLine("Pairs where a < b:"); + foreach (var pair in pairs) + { + Console.WriteLine($"{pair.a} is less than {pair.b}"); + } + #endregion + return 0; + } + + public int SelectFromChildSequence() + { + #region select-many-drilldown + List customers = GetCustomerList(); + + var orders = from c in customers + from o in c.Orders + where o.Total < 500.00M + select (c.CustomerID, o.OrderID, o.Total); + + foreach(var order in orders) + { + Console.WriteLine($"Customer: {order.CustomerID}, Order: {order.OrderID}, Total value: {order.Total}"); + } + #endregion + return 1; + } + + public int SelectManyWithWhere() + { + #region select-many-filter + List customers = GetCustomerList(); + + var orders = from c in customers + from o in c.Orders + where o.OrderDate >= new DateTime(1998, 1, 1) + select (c.CustomerID, o.OrderID, o.OrderDate); + + foreach (var order in orders) + { + Console.WriteLine($"Customer: {order.CustomerID}, Order: {order.OrderID}, Total date: {order.OrderDate.ToShortDateString()}"); + } + #endregion + return 0; + } + + public int SelectManyWhereAssignment() + { + #region select-many-assignment + List customers = GetCustomerList(); + + var orders = from c in customers + from o in c.Orders + where o.Total >= 2000.0M + select (c.CustomerID, o.OrderID, o.Total); + + foreach (var order in orders) + { + Console.WriteLine($"Customer: {order.CustomerID}, Order: {order.OrderID}, Total value: {order.Total}"); + } + #endregion + return 0; + } + + public int SelectMultipleWhereClauses() + { + #region multiple-where-clauses + List customers = GetCustomerList(); + + DateTime cutoffDate = new DateTime(1997, 1, 1); + + var orders = from c in customers + where c.Region == "WA" + from o in c.Orders + where o.OrderDate >= cutoffDate + select (c.CustomerID, o.OrderID); + + foreach (var order in orders) + { + Console.WriteLine($"Customer: {order.CustomerID}, Order: {order.OrderID}"); + } + #endregion + return 0; + } + + public int IndexedSelectMany() + { + #region indexed-select-many + List customers = GetCustomerList(); + + var customerOrders = + customers.SelectMany( + (cust, custIndex) => + cust.Orders.Select(o => "Customer #" + (custIndex + 1) + + " has an order with OrderID " + o.OrderID)); + + foreach (var order in customerOrders) + { + Console.WriteLine(order); + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/Quantifiers.cs b/101-linq-samples/src/Quantifiers.cs new file mode 100644 index 0000000..250ef88 --- /dev/null +++ b/101-linq-samples/src/Quantifiers.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Try101LinqSamples +{ + public class Quantifiers + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int AnyMatchingElements() + { + #region any-matches + string[] words = { "believe", "relief", "receipt", "field" }; + + bool iAfterE = words.Any(w => w.Contains("ei")); + + Console.WriteLine($"There is a word that contains in the list that contains 'ei': {iAfterE}"); + #endregion + return 0; + } + + public int GroupedAnyMatchedElements() + { + #region any-grouped + List products = GetProductList(); + var productGroups = from p in products + group p by p.Category into g + where g.Any(p => p.UnitsInStock == 0) + select (Category: g.Key, Products: g); + + foreach(var group in productGroups) + { + Console.WriteLine(group.Category); + foreach(var product in group.Products) + { + Console.WriteLine($"\t{product}"); + } + } + #endregion + return 0; + } + + public int AllMatchedElements() + { + #region all-match + int[] numbers = { 1, 11, 3, 19, 41, 65, 19 }; + + bool onlyOdd = numbers.All(n => n % 2 == 1); + + Console.WriteLine($"The list contains only odd numbers: {onlyOdd}"); + #endregion + return 0; + } + + public int GroupedAllMatchedElements() + { + #region all-grouped + List products = GetProductList(); + + var productGroups = from p in products + group p by p.Category into g + where g.All(p => p.UnitsInStock > 0) + select (Category: g.Key, Products: g); + + foreach (var group in productGroups) + { + Console.WriteLine(group.Category); + foreach (var product in group.Products) + { + Console.WriteLine($"\t{product}"); + } + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/QueryExecution.cs b/101-linq-samples/src/QueryExecution.cs new file mode 100644 index 0000000..ab7ff05 --- /dev/null +++ b/101-linq-samples/src/QueryExecution.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; + +namespace Try101LinqSamples +{ + public class QueryExecution + { + public int DeferredExecution() + { + #region deferred-execution + // Sequence operators form first-class queries that + // are not executed until you enumerate over them. + + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + int i = 0; + var q = from n in numbers + select ++i; + + // Note, the local variable 'i' is not incremented + // until each element is evaluated (as a side-effect): + foreach (var v in q) + { + Console.WriteLine($"v = {v}, i = {i}"); + } + #endregion + return 0; + } + + public int EagerExecution() + { + #region eager-execution + // Methods like ToList() cause the query to be + // executed immediately, caching the results. + + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + int i = 0; + var q = (from n in numbers + select ++i) + .ToList(); + + // The local variable i has already been fully + // incremented before we iterate the results: + foreach (var v in q) + { + Console.WriteLine($"v = {v}, i = {i}"); + } + #endregion + return 0; + } + + public int ReuseQueryDefinition() + { + #region reuse-query + // Deferred execution lets us define a query once + // and then reuse it later after data changes. + + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + var lowNumbers = from n in numbers + where n <= 3 + select n; + + Console.WriteLine("First run numbers <= 3:"); + foreach (int n in lowNumbers) + { + Console.WriteLine(n); + } + + for (int i = 0; i < 10; i++) + { + numbers[i] = -numbers[i]; + } + + // During this second run, the same query object, + // lowNumbers, will be iterating over the new state + // of numbers[], producing different results: + Console.WriteLine("Second run numbers <= 3:"); + foreach (int n in lowNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/Restrictions.cs b/101-linq-samples/src/Restrictions.cs new file mode 100644 index 0000000..c261833 --- /dev/null +++ b/101-linq-samples/src/Restrictions.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class Restrictions + { + public List GetProductList() => Products.ProductList; + + public List GetCustomerList() => Customers.CustomerList; + + public int LowNumbers() + { + #region where-syntax + int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; + + var lowNums = from num in numbers + where num < 5 + select num; + + Console.WriteLine("Numbers < 5:"); + foreach (var x in lowNums) + { + Console.WriteLine(x); + } + #endregion + return 0; + } + + public int ProductsOutOfStock() + { + #region where-property + List products = GetProductList(); + + var soldOutProducts = from prod in products + where prod.UnitsInStock == 0 + select prod; + + Console.WriteLine("Sold out products:"); + foreach (var product in soldOutProducts) + { + Console.WriteLine($"{product.ProductName} is sold out!"); + } + #endregion + return 0; + } + + public int ExpensiveProductsInStock() + { + #region where-multiple-properties + List products = GetProductList(); + + var expensiveInStockProducts = from prod in products + where prod.UnitsInStock > 0 && prod.UnitPrice > 3.00M + select prod; + + Console.WriteLine("In-stock products that cost more than 3.00:"); + foreach (var product in expensiveInStockProducts) + { + Console.WriteLine($"{product.ProductName} is in stock and costs more than 3.00."); + } + #endregion + return 0; + } + + public int DisplayCustomerOrders() + { + #region where-drilldown + List customers = GetCustomerList(); + + var waCustomers = from cust in customers + where cust.Region == "WA" + select cust; + + Console.WriteLine("Customers from Washington and their orders:"); + foreach (var customer in waCustomers) + { + Console.WriteLine($"Customer {customer.CustomerID}: {customer.CompanyName}"); + foreach (var order in customer.Orders) + { + Console.WriteLine($" Order {order.OrderID}: {order.OrderDate}"); + } + } + #endregion + return 0; + } + + public int IndexedWhere() + { + #region where-indexed + string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; + + var shortDigits = digits.Where((digit, index) => digit.Length < index); + + Console.WriteLine("Short digits:"); + foreach (var d in shortDigits) + { + Console.WriteLine($"The word {d} is shorter than its value."); + } + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/SequenceOperations.cs b/101-linq-samples/src/SequenceOperations.cs new file mode 100644 index 0000000..9c549b9 --- /dev/null +++ b/101-linq-samples/src/SequenceOperations.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class SequenceOperations + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int EqualSequence() + { + #region equal-sequence + var wordsA = new string[] { "cherry", "apple", "blueberry" }; + var wordsB = new string[] { "cherry", "apple", "blueberry" }; + + bool match = wordsA.SequenceEqual(wordsB); + + Console.WriteLine($"The sequences match: {match}"); + #endregion + return 0; + } + + // Combine in Markdown.s + public int Linq97() + { + #region not-equal-sequence + var wordsA = new string[] { "cherry", "apple", "blueberry" }; + var wordsB = new string[] { "apple", "blueberry", "cherry" }; + + bool match = wordsA.SequenceEqual(wordsB); + + Console.WriteLine($"The sequences match: {match}"); + #endregion + return 0; + } + + public int ConcatSeries() + { + #region concat-series + int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; + int[] numbersB = { 1, 3, 5, 7, 8 }; + + var allNumbers = numbersA.Concat(numbersB); + + Console.WriteLine("All numbers from both arrays:"); + foreach (var n in allNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int ConcatProjection() + { + #region concat-projections + List customers = GetCustomerList(); + List products = GetProductList(); + + var customerNames = from c in customers + select c.CompanyName; + var productNames = from p in products + select p.ProductName; + + var allNames = customerNames.Concat(productNames); + + Console.WriteLine("Customer and product names:"); + foreach (var n in allNames) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int DotProduct() + { + #region dot-product + int[] vectorA = { 0, 2, 4, 5, 6 }; + int[] vectorB = { 1, 3, 5, 7, 8 }; + + int dotProduct = vectorA.Zip(vectorB, (a, b) => a * b).Sum(); + + Console.WriteLine($"Dot product: {dotProduct}"); + #endregion + return 0; + } + } +} diff --git a/101-linq-samples/src/SetOperations.cs b/101-linq-samples/src/SetOperations.cs new file mode 100644 index 0000000..80e19ea --- /dev/null +++ b/101-linq-samples/src/SetOperations.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Try101LinqSamples +{ + public class SetOperations + { + public List GetProductList() => Products.ProductList; + public List GetCustomerList() => Customers.CustomerList; + + public int DistinctSyntax() + { + #region distinct-syntax + int[] factorsOf300 = { 2, 2, 3, 5, 5 }; + + var uniqueFactors = factorsOf300.Distinct(); + + Console.WriteLine("Prime factors of 300:"); + foreach (var f in uniqueFactors) + { + Console.WriteLine(f); + } + #endregion + return 0; + } + + public int DistinctPropertyValues() + { + #region distinct-property-values + List products = GetProductList(); + + var categoryNames = (from p in products + select p.Category) + .Distinct(); + + Console.WriteLine("Category names:"); + foreach (var n in categoryNames) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int UnionSyntax() + { + #region union-syntax + int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; + int[] numbersB = { 1, 3, 5, 7, 8 }; + + var uniqueNumbers = numbersA.Union(numbersB); + + Console.WriteLine("Unique numbers from both arrays:"); + foreach (var n in uniqueNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int UnionOfQueryResults() + { + #region union-query-results + List products = GetProductList(); + List customers = GetCustomerList(); + + var productFirstChars = from p in products + select p.ProductName[0]; + var customerFirstChars = from c in customers + select c.CompanyName[0]; + + var uniqueFirstChars = productFirstChars.Union(customerFirstChars); + + Console.WriteLine("Unique first letters from Product names and Customer names:"); + foreach (var ch in uniqueFirstChars) + { + Console.WriteLine(ch); + } + #endregion + return 0; + } + + public int IntersectSynxtax() + { + #region intersect-syntax + int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; + int[] numbersB = { 1, 3, 5, 7, 8 }; + + var commonNumbers = numbersA.Intersect(numbersB); + + Console.WriteLine("Common numbers shared by both arrays:"); + foreach (var n in commonNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int IntersectQueryResults() + { + #region intersect-different-queries + List products = GetProductList(); + List customers = GetCustomerList(); + + var productFirstChars = from p in products + select p.ProductName[0]; + var customerFirstChars = from c in customers + select c.CompanyName[0]; + + var commonFirstChars = productFirstChars.Intersect(customerFirstChars); + + Console.WriteLine("Common first letters from Product names and Customer names:"); + foreach (var ch in commonFirstChars) + { + Console.WriteLine(ch); + } + #endregion + return 0; + } + + public int DifferenceOfSets() + { + #region except-syntax + int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; + int[] numbersB = { 1, 3, 5, 7, 8 }; + + IEnumerable aOnlyNumbers = numbersA.Except(numbersB); + + Console.WriteLine("Numbers in first array but not second array:"); + foreach (var n in aOnlyNumbers) + { + Console.WriteLine(n); + } + #endregion + return 0; + } + + public int DifferenceOfQueries() + { + #region difference-of-queries + List products = GetProductList(); + List customers = GetCustomerList(); + + var productFirstChars = from p in products + select p.ProductName[0]; + var customerFirstChars = from c in customers + select c.CompanyName[0]; + + var productOnlyFirstChars = productFirstChars.Except(customerFirstChars); + + Console.WriteLine("First letters from Product names, but not from Customer names:"); + foreach (var ch in productOnlyFirstChars) + { + Console.WriteLine(ch); + } + #endregion + return 1; + } + } +} diff --git a/101-linq-samples/src/Try101LinqSamples.csproj b/101-linq-samples/src/Try101LinqSamples.csproj new file mode 100644 index 0000000..32d1ab3 --- /dev/null +++ b/101-linq-samples/src/Try101LinqSamples.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp3.0 + 8.0 + + + + + + + diff --git a/101-linq-samples/src/Try101LinqSamples.sln b/101-linq-samples/src/Try101LinqSamples.sln new file mode 100644 index 0000000..0d96759 --- /dev/null +++ b/101-linq-samples/src/Try101LinqSamples.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Try101LinqSamples", "Try101LinqSamples.csproj", "{7B869FAB-42BF-43CD-9877-B9F6185C2C6A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7B869FAB-42BF-43CD-9877-B9F6185C2C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B869FAB-42BF-43CD-9877-B9F6185C2C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B869FAB-42BF-43CD-9877-B9F6185C2C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B869FAB-42BF-43CD-9877-B9F6185C2C6A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal