Projection Operators

Select Anonymous Types 2

This sample uses select to produce a sequence containing text representations of digits and whether their length is even or odd.

Code:

            public void DataSetLinq10()
            {

                var numbers = testDS.Tables["Numbers"].AsEnumerable();
                var digits = testDS.Tables["Digits"];
                string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

                var digitOddEvens = numbers.
                    Select(n => new
                    {
                        Digit = digits.Rows[n.Field("number")]["digit"],
                        Even = (n.Field("number") % 2 == 0)
                    });

                foreach (var d in digitOddEvens)
                {
                    Log.WriteLine("The digit {0} is {1}.", d.Digit, d.Even ? "even" : "odd");
                }
            }

Result:

Select - Anonymous Types 3

This sample uses select to produce a sequence containing some properties of Products, including UnitPrice which is renamed to Price in the resulting type.

Code:

            public void DataSetLinq11()
            {

                var products = testDS.Tables["Products"].AsEnumerable();

                var productInfos = products.
                    Select(n => new{
                        ProductName = n.Field("ProductName"),
                        Category = n.Field("Category"),
                        Price = n.Field("UnitPrice")
                    });

                Log.WriteLine("Product Info:");
                foreach (var productInfo in productInfos)
                {
                    Log.WriteLine("{0} is in the category {1} and costs {2} per unit.", productInfo.ProductName, productInfo.Category, productInfo.Price);
                }
            }

Result:

Select - Indexed

This sample uses an indexed Select clause to determine if the value of ints in an array match their position in the array.

Code:

            public void DataSetLinq12()
            {

                var numbers = testDS.Tables["Numbers"].AsEnumerable();

                var numsInPlace = numbers.Select((num, index) => new
                {
                    Num = num.Field("number"),
                    InPlace = (num.Field("number") == index)
                });

                Log.WriteLine("Number: In-place?");
                foreach (var n in numsInPlace)
                {
                    Log.WriteLine("{0}: {1}", n.Num, n.InPlace);
                }
            }

Result:

Skip - Filtered

This sample combines select and where to make a simple query that returns the text form of each digit less than 5.

Code:

            public void DataSetLinq13()
            {

                var numbers = testDS.Tables["Numbers"].AsEnumerable();
                var digits = testDS.Tables["Digits"];

                var lowNums = numbers.Where(n => n.Field("number") < 5).Select(n => digits.Rows[n.Field("number")].Field("digit"));

                Log.WriteLine("Numbers < 5:");
                foreach (var num in lowNums)
                {
                    Log.WriteLine(num);
                }
            }

Result:

SelectMany - Compound from 1

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.

Code:

            public void DataSetLinq14()
            {

                var numbersA = testDS.Tables["NumbersA"].AsEnumerable();
                var numbersB = testDS.Tables["NumbersB"].AsEnumerable();

                var pairs = numbersA.SelectMany(a => numbersB, (a, b) => new {a, b})
                        .Where(@t => @t.a.Field("number") < @t.b.Field("number"))
                        .Select(@t => new {a = @t.a.Field("number"), b = @t.b.Field("number")});

                Log.WriteLine("Pairs where a < b:");
                foreach (var pair in pairs)
                {
                    Log.WriteLine("{0} is less than {1}", pair.a, pair.b);
                }
            }

Result:

SelectMany - Compound from 2

This sample uses a compound from clause to select all orders where the order total is less than 500.00.

Code:

            public void DataSetLinq15()
            {

                var customers = testDS.Tables["Customers"].AsEnumerable();
                var orders = testDS.Tables["Orders"].AsEnumerable();

                var smallOrders =
                    customers.SelectMany(c => orders, (c, o) => new {c, o})
                        .Where(@t => @t.c.Field("CustomerID") == @t.o.Field("CustomerID") && @t.o.Field("Total") < 500.00M)
                        .Select(@t => new {
                            CustomerID = @t.c.Field("CustomerID"),
                            OrderID = @t.o.Field("OrderID"),
                            Total = @t.o.Field("Total")
                        });
                ObjectDumper.Write(smallOrders);
            }

Result:

SelectMany - Compound from 3

This sample uses a compound from clause to select all orders where the order was made in 1998 or later.

Code:

            public void DataSetLinq16()
            {

                var customers = testDS.Tables["Customers"].AsEnumerable();
                var orders = testDS.Tables["Orders"].AsEnumerable();

                var myOrders =
                    customers.SelectMany(c => orders, (c, o) => new {c, o}).
                    Where(@t => @t.c.Field("CustomerID") == @t.o.Field("CustomerID") && @t.o.Field("OrderDate") >= new DateTime(1998, 1, 1)).
                    Select(@t => new { 
                        CustomerID = @t.c.Field("CustomerID"), 
                        OrderID = @t.o.Field("OrderID"), 
                        OrderDate = @t.o.Field("OrderDate")});
                ObjectDumper.Write(myOrders);
            }

Result:

SelectMany - from 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.

Code:

            public void DataSetLinq17()
            {

                var customers = testDS.Tables["Customers"].AsEnumerable();
                var orders = testDS.Tables["Orders"].AsEnumerable();

                var myOrders =
                    customers.SelectMany(c => orders, (c, o) => new {c, o})
                        .Select(@t => new {@t, total = @t.o.Field("Total")})
                        .Where(@t => @t.@t.c.Field("CustomerID") == @t.@t.o.Field("CustomerID") && @t.total >= 2000.0M)
                        .Select(@t => 
                            new {
                                CustomerID = @t.@t.c.Field("CustomerID"), 
                                OrderID = @t.@t.o.Field("OrderID"), @t.total
                            });

                ObjectDumper.Write(myOrders);
            }

Result:

SelectMany - Multiple from

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.

Code:

            public void DataSetLinq18()
            {

                var customers = testDS.Tables["Customers"].AsEnumerable();
                var orders = testDS.Tables["Orders"].AsEnumerable();
                DateTime cutoffDate = new DateTime(1997, 1, 1);

                var myOrders =
                    customers.Where(c => c.Field("Region") == "WA").SelectMany(c => orders, (c, o) => new {c, o})
                    .Where(@t => @t.c.Field("CustomerID") == @t.o.Field("CustomerID") && (DateTime) @t.o["OrderDate"] >= cutoffDate)
                    .Select(@t => new {
                        CustomerID = @t.c.Field("CustomerID"), 
                        OrderID = @t.o.Field("OrderID")
                    });

                ObjectDumper.Write(myOrders);
            }

Result:

SelectMany - Indexed

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.

Code:

            public void DataSetLinq19()
            {

                var customers = testDS.Tables["Customers"].AsEnumerable();
                var orders = testDS.Tables["Orders"].AsEnumerable();

                var customerOrders =
                    customers.SelectMany(
                        (cust, custIndex) =>
                        orders.Where(o => cust.Field("CustomerID") == o.Field("CustomerID"))
                            .Select(o => new { CustomerIndex = custIndex + 1, OrderID = o.Field("OrderID") }));

                foreach (var c in customerOrders)
                {
                    Log.WriteLine("Customer Index: " + c.CustomerIndex +
                                        " has an order with OrderID " + c.OrderID);
                }
            }

Result:

Select - Simple 1

This sample uses select to produce a sequence of ints one higher than those in an existing array of ints.

Code:

            public void DataSetLinq6()
            {

                var numbers = testDS.Tables["Numbers"].AsEnumerable();

                var numsPlusOne = numbers.Select(n => n.Field(0) + 1);

                Log.WriteLine("Numbers + 1:");
                foreach (var i in numsPlusOne)
                {
                    Log.WriteLine(i);
                }
            }

Result:

Select - Simple 2

This sample uses select to return a sequence of just the names of a list of products.

Code:

            public void DataSetLinq7()
            {

                var products = testDS.Tables["Products"].AsEnumerable();

                var productNames =
                    products.Select(p => p.Field("ProductName"));

                Log.WriteLine("Product Names:");
                foreach (var productName in productNames)
                {
                    Log.WriteLine(productName);
                }
            }

Result:

Select - Transformation

This sample uses select to produce a sequence of strings representing the text version of a sequence of ints.

Code:

            public void DataSetLinq8()
            {

                var numbers = testDS.Tables["Numbers"].AsEnumerable();
                string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

                var textNums = numbers.Select(p => strings[p.Field("number")]);

                Log.WriteLine("Number strings:");
                foreach (var s in textNums)
                {
                    Log.WriteLine(s);
                }
            }

Result:

Select - Anonymous Types 1

This sample uses select to produce a sequence of the uppercase and lowercase versions of each word in the original array.

Code:

            public void DataSetLinq9()
            {

                var words = testDS.Tables["Words"].AsEnumerable();

                var upperLowerWords = words.Select(p => new
                {
                    Upper = (p.Field(0)).ToUpper(),
                    Lower = (p.Field(0)).ToLower()
                });

                foreach (var ul in upperLowerWords)
                {
                    Log.WriteLine("Uppercase: " + ul.Upper + ", Lowercase: " + ul.Lower);
                }
            }

Result: