Linqproject

[Back to LINQ examples] View Original LINQ Code

Select - Simple 1

This sample produces a sequence of ints one higher than those in an existing array of ints.

This is one of the LINQ examples designed to show LINQ operating over standard Java collections. In this case the batch version is just ordinary Java iteration.

public void Batch6() {
  int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

  print("Numbers + 1:");
  for (int i : numbers)
    print("{0}", i + 1);
}

Original LINQ code:

public void Linq6()
{
    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);
    }
}

Select - Simple 2

This sample returns a sequence of just the names of a list of products.

This is one of the LINQ examples designed to show LINQ operating over standard Java collections. In this case the batch version is just ordinary Java iteration.

public void Batch7() {
  print("Product Names:");
  for (Northwind db : connection)
    for (Product p : db.Products)
      print("{0}", p.ProductName);
}

Generated SQL code:

SELECT T1.ProductName AS g0
FROM Products T1

Original LINQ code:

public void Linq7()
{
    List<Product> products = GetProductList();

    var productNames =
        from p in products
        select p.ProductName;

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

Select - Transformation

This sample produces a sequence of strings representing the text version of a sequence of ints.

This is one of the LINQ examples designed to show LINQ operating over standard Java collections. In this case the batch version is just ordinary Java iteration.

public void Batch8() {
  int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
  String[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

  print("Number strings:");
  for (int n : numbers)
    print(strings[n]);
}

Original LINQ code:

public void Linq8()
{
    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);
    }
}

Select - Anonymous Types 1

This sample produces a sequence of the uppercase and lowercase versions of each word in the original array.

There is no reason to create an intermediate data structure with an anonymous type for this example.

public void Batch9() {
  String[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
  for (String w : words)
    print("Uppercase: {0}, Lowercase: {1}", w.toUpperCase(), w.toLowerCase());
}

Original LINQ code:

public void Linq9()
{
    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: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
    }
}

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.

There is no reason to create an intermediate data structure with an anonymous type for this example.

public void Batch10() {
  int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
  String[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

  for (int n : numbers)
    print("The digit {0} is {1}.", strings[n], (n % 2 == 0) ? "even" : "odd");
}

Original LINQ code:

public void Linq10()
{
    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 {0} is {1}.", d.Digit, d.Even ? "even" : "odd");
    }
}

Select - Anonymous Types 3

This sample produces a sequence containing some properties of Products.

public void Batch11() {
  print("Product Info:");
  for (Northwind db : connection)
    for (Product p : db.Products)
      print("{0} is : the category {1} and costs {2} per unit.", 
          p.ProductName, p.Category.CategoryName, p.UnitPrice);
}

Generated SQL code:

SELECT T1.ProductName AS g1, T2.CategoryName AS g2, T1.UnitPrice AS g3
FROM Products T1 INNER JOIN Categories T2 ON (T2.CategoryID=T1.CategoryID)

Original LINQ code:

public void Linq11()
{
    List<Product> products = GetProductList();

    var productInfos =
        from p in products
        select new { p.ProductName, p.Category, Price = p.UnitPrice };

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

Select - Indexed

This sample determines if the value of ints in an array match their position in the array.

This is one of the LINQ examples designed to show LINQ operating over standard Java collections. In this case the batch version is just ordinary Java iteration.

public void Batch12() {
   int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

   print("Number: In-place?");
   int index = 0;
   for (int n : numbers) {
     print("{0}: {1}", n, (n == index));
     index++;
  }
}

Original LINQ code:

public void Linq12()
{
    int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

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

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

Select - Filtered

This sample returns the text form of each digit less than 5.

This is one of the LINQ examples designed to show LINQ operating over standard Java collections. In this case the batch version is just ordinary Java iteration.

public void Batch13() {
  int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
  String[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

  print("Numbers < 5:");
  for (int n : numbers)
    if (n < 5)
      print(digits[n]);
}

Original LINQ code:

public void Linq13()
{
    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);
    }
}

SelectMany - Compound from 1

This sample prints all pairs of numbers such that the number from array numbersA is less than the number from array numbersB.

This is another LINQ examples that shows LINQ operating over standard Java collections. In this case the batch version is just ordinary Java iteration.

public void Batch14() {
    int[] numbersA = {0, 2, 4, 5, 6, 8, 9};
    int[] numbersB = {1, 3, 5, 7, 8};

    print("Pairs where a < b:");
    for (int a : numbersA)
      for (int b : numbersB)
        if (a < b)
          print("{0} is less than {1}", a, b);
  }

Original LINQ code:

public void Linq14()
{
    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 new { a, b };

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

SelectMany - Compound from 2

This sample prints all orders where the order total is less than 500.00.

The LINQ solution uses a compound from clause. The batch solution uses nested for loops, and sums the total of every item in each order. Note that there is a discrepancy between the data apparently used for the LINQ samples and the data in the Northwind database. An order in the LINQ data includes a total. An order in the Northwind database participates in a one-to-many relationship with (unit-price, unit-quantity) pairs, which the batch solution uses to compute a total.

public void Batch15() {
  for (Northwind db : connection)
    for (Customer c : db.Customers)
      for (Order o : c.Orders) {
        double total = o.OrderDetails.dsum(Order_Details.ByTotal);
        if (total < 500)
          print("Customer={0} Order={1} Total={2}", 
                 o.Customer.CustomerID, o.OrderID, total);
}

Generated SQL code:

SELECT 
    T1.CustomerID AS id
FROM Customers T1
ORDER BY id ASC

SELECT 
    T3.CustomerID AS parent,
    (SELECT SUM((T4.UnitPrice*T4.Quantity))
FROM Order_Details T4
WHERE (T4.OrderID=T3.OrderID)) AS g7,
    T5.CustomerID AS g4,
    T3.OrderID AS g5,
    (SELECT SUM((T4.UnitPrice*T4.Quantity))
FROM Order_Details T4
WHERE (T4.OrderID=T3.OrderID)) AS g6
FROM Orders T3
INNER JOIN Customers T5 ON (T5.CustomerID=T3.CustomerID)
WHERE ((SELECT SUM((T4.UnitPrice*T4.Quantity))
FROM Order_Details T4
WHERE (T4.OrderID=T3.OrderID))<500)
ORDER BY parent ASC

Original LINQ code:

public void Linq15()
{
    List<Customer> customers = GetCustomerList();

    var orders =
        from c in customers
        from o in c.Orders
        where o.Total < 500.00M
        select new { c.CustomerID, o.OrderID, o.Total };

    ObjectDumper.Write(orders);
}

SelectMany - Compound from 3

This sample prints all orders where the order was made in 1998 or later.

The LINQ solution uses a compound from clause. The batch solution uses nested for loops.

public void Batch16() {
  for (Northwind db : connection)
    for (Customer c : db.Customers)
      for (Order o : c.Orders)
        if (o.OrderDate.after(Date.valueOf("1998-1-1")))
          print("Customer={0} Order={1} Date={2}", c.CustomerID, o.OrderID, o.OrderDate);
}

Generated SQL code:

SELECT 
  T1.CustomerID AS id
FROM Customers T1
ORDER BY id ASC

SELECT 
  T3.CustomerID AS parent,
  T4.CustomerID AS g63,
  T3.OrderID AS g64,
  T3.OrderDate AS g65
FROM Orders T3
INNER JOIN Customers T4 ON (T4.CustomerID=T3.CustomerID)
WHERE (T3.OrderDate>?)
ORDER BY parent ASC

Original LINQ code:

public void Linq16()
{
    List<Customer> customers = GetCustomerList();

    var orders =
        from c in customers
        from o in c.Orders
        where o.OrderDate >= new DateTime(1998, 1, 1)
        select new { c.CustomerID, o.OrderID, o.OrderDate };

    ObjectDumper.Write(orders);
}

SelectMany - Compound from Assignment

This sample prints all orders where the order total is greater than 2000.00.

The LINQ solution uses a compound from clause. The batch solution uses nested for loops. Both versions use the value of an order's total twice, but load each value only once. The LINQ version accomplishes the load-once behavior using from assignment. The batch version accomplishes it using an assignment to freight in the inner loop.

public void Batch17() {
  for (Northwind db : connection)
    for (Customer c : db.Customers)
      for (Order o : c.Orders) {
        double total = o.OrderDetails.dsum(Order_Details.ByTotal);
        if (total > 2000)
          print("Customer={0} Order={1} Total={2}", 
                  c.CustomerID, o.OrderID, total);
        }
}

Generated SQL code:

SELECT 
    T1.CustomerID AS id
FROM Customers T1
ORDER BY id ASC

SELECT 
    T3.CustomerID AS parent,
    (SELECT SUM((T4.UnitPrice*T4.Quantity))
FROM Order_Details T4
WHERE (T4.OrderID=T3.OrderID)) AS g15,
    T5.CustomerID AS g12,
    T3.OrderID AS g13,
    (SELECT SUM((T4.UnitPrice*T4.Quantity))
FROM Order_Details T4
WHERE (T4.OrderID=T3.OrderID)) AS g14
FROM Orders T3
INNER JOIN Customers T5 ON (T5.CustomerID=T3.CustomerID)
WHERE ((SELECT SUM((T4.UnitPrice*T4.Quantity))
FROM Order_Details T4
WHERE (T4.OrderID=T3.OrderID))>2000)
ORDER BY parent ASC

Original LINQ code:

public void Linq17()
{
    List<Customer> customers = GetCustomerList();

    var orders =
        from c in customers
        from o in c.Orders
        where o.Total >= 2000.0M
        select new { c.CustomerID, o.OrderID, o.Total };

    ObjectDumper.Write(orders);
}

SelectMany - Multiple from

This sample prints all orders where the customer is from Washington and the order was placed after a January 1, 1997.

Both version want to optimize the query. The LINQ version contains multiple from clauses so that the date restriction is applied after the location restriction. The batch version generates SQL queries that have the same effect by using nested if statements and for loops.

public void Batch18() {
  Date cutoffDate = Date.valueOf("1997-1-1");
  for (Northwind db : connection)
    for (Customer c : db.Customers)
      if (c.Region == "WA")
        for (Order o : c.Orders)
          if (o.OrderDate.after(cutoffDate))
            print("Customer={0} Order={1}", c.CustomerID, o.OrderID);
}

Generated SQL code:

SELECT 
  T1.CustomerID AS id
FROM Customers T1
WHERE (T1.Region="WA")
ORDER BY id ASC

SELECT 
  T3.CustomerID AS parent,
  T4.CustomerID AS g16,
  T3.OrderID AS g17
FROM Orders T3
INNER JOIN Customers T4 ON (T4.CustomerID=T3.CustomerID)
WHERE ((T3.OrderDate>?)
AND (T4.Region="WA"))
ORDER BY parent ASC

Original LINQ code:

public void Linq18()
{
    List<Customer> 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 new { c.CustomerID, o.OrderID };

    ObjectDumper.Write(orders);
}

SelectMany - Indexed

This sample prints all the order in the database, indexed by customer. The customer's index is determined by the order in which the query returns the customer records.

The LINQ version uses an indexed SelectMany call to compute a customer's index. The batch version computes a counter. The differences in the two implementations highlights the benefits of batches when mixing program computation (e.g., keeping a counter) and database computation (e.g., associating a customer with their orders).

public void Batch19() {
  int index = 0;
  for (Northwind db : connection)
    for (Customer cust : db.Customers) {
      index++;
      for (Order o : cust.Orders)
        print("Customer #{0} has an order with OrderID {1}", index, o.OrderID);
    }
}

Generated SQL code:

SELECT 
  T1.CustomerID AS id
FROM Customers T1
ORDER BY id ASC

SELECT 
  T3.CustomerID AS parent,
  T3.OrderID AS g18
FROM Orders T3
ORDER BY parent ASC

Original LINQ code:

public void Linq19()
{
    List<Customer> customers = GetCustomerList();

    var customerOrders =
        customers.SelectMany(
            (cust, custIndex) =>
            cust.Orders.Select(o => "Customer #" + (custIndex + 1) +
                                    " has an order with OrderID " + o.OrderID));

    ObjectDumper.Write(customerOrders);
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License